import React, {useEffect, useState} from 'react'; import { Dialog, DialogContent, IconButton, Box, Typography, Slider, FormControl, InputLabel, Select, MenuItem, Checkbox, ListItemText, Card, CardContent, CardMedia, Button, CircularProgress, AppBar, Toolbar, InputAdornment, TextField, TextField as MuiTextField, DialogTitle, DialogActions, Snackbar, Alert, Drawer, Badge } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; import AddCircleIcon from '@mui/icons-material/AddCircle'; import FilterListIcon from '@mui/icons-material/FilterList'; import SearchIcon from "@mui/icons-material/Search"; import {onGetAllComponents, onGetAuthState, onSuggestComponent} from '../pages/+Layout.telefunc' import {onGetCompatibleComponents} from '../pages/forge/forge.telefunc'; import ComponentDetailsDialog from "./ComponentDetailsDialog"; const formatMoney = (amount: number) => `$${Number(amount).toFixed(2)}`; export default function ComponentDialog({open, category, onClose, mode, onSelect, currentBuildId}: any) { const [components, setComponents] = useState([]); const [loading, setLoading] = useState(false); const [selectedComponent, setSelectedComponent] = useState(null); const [priceRange, setPriceRange] = useState([0, 2000]); const [selectedBrands, setSelectedBrands] = useState([]); const [availableBrands, setAvailableBrands] = useState([]); const [sortOrder, setSortOrder] = useState('default'); const [tempSearchQuery, setTempSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState(""); const [suggestOpen, setSuggestOpen] = useState(false); const [suggestForm, setSuggestForm] = useState({ link: '', description: '', componentType: category || '' }); const [suggestLoading, setSuggestLoading] = useState(false); const [snackbarOpen, setSnackbarOpen] = useState(false); const [snackbarMessage, setSnackbarMessage] = useState(""); const [userId, setUserId] = useState(null); const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false); useEffect(() => { if (open && category) { setSuggestForm({ link: '', description: '', componentType: category }); } }, [open, category]); useEffect(() => { const timeoutId = setTimeout(() => { setSearchQuery(tempSearchQuery); }, 300); return () => clearTimeout(timeoutId); }, [tempSearchQuery]); useEffect(() => { if (open && category) { setSelectedBrands([]); setSortOrder('price_desc'); setTempSearchQuery(''); setSearchQuery(''); setPriceRange([0, 2000]); } }, [open, category]); useEffect(() => { if (open) { onGetAuthState().then(userData => { setUserId(userData.userId); }); } }, [open]); useEffect(() => { if (open && category) { setLoading(true); setSortOrder('price_desc'); const shouldUseCompatibility = mode === 'forge' && currentBuildId; const fetcher = shouldUseCompatibility ? onGetCompatibleComponents({ buildId: currentBuildId, componentType: category, limit: 100, sort: 'price_desc' }) : onGetAllComponents({ componentType: category, limit: 100, sort: 'price_desc' }); fetcher .then((data) => { const comps = data || []; setComponents(comps); const brands = Array.from(new Set(comps.map((c: any) => c.brand))); setAvailableBrands(brands as string[]); const maxPrice = comps.length > 0 ? Math.max(...comps.map((c: any) => Number(c.price))) : 2000; setPriceRange([0, Math.ceil(maxPrice)]); }) .catch((err) => { console.error('[Dialog] fetch error:', err); setComponents([]); }) .finally(() => setLoading(false)); } }, [open, category, mode, currentBuildId]); const handleSuggestChange = (e: React.ChangeEvent) => { setSuggestForm({ ...suggestForm, [e.target.name]: e.target.value }); } const submitSuggestion = async () => { if (!userId) { setSnackbarMessage("Please login to submit suggestions!"); setSnackbarOpen(true); return; } if (!suggestForm.link || !suggestForm.description) { setSnackbarMessage("Please fill in all fields!"); setSnackbarOpen(true); return; } setSuggestLoading(true); try { const suggestionId = await onSuggestComponent({ link: suggestForm.link, description: suggestForm.description, componentType: suggestForm.componentType }); setSnackbarMessage("Suggestion submitted! Admin will review it."); setSnackbarOpen(true); setSuggestOpen(false); setSuggestForm({link: '', description: '', componentType: category || ''}); } catch (error) { console.error('Suggestion error:', error); setSnackbarMessage("Failed to submit suggestion. Try again."); setSnackbarOpen(true); } finally { setSuggestLoading(false); } }; let processedComponents = components.filter(comp => { const matchesBrand = selectedBrands.length === 0 || selectedBrands.includes(comp.brand); const matchesPrice = Number(comp.price) >= priceRange[0] && Number(comp.price) <= priceRange[1]; const matchesSearch = searchQuery === "" || comp.name.toLowerCase().includes(searchQuery.toLowerCase()) || comp.brand.toLowerCase().includes(searchQuery.toLowerCase()); return matchesBrand && matchesPrice && matchesSearch; }); if (sortOrder === 'price_asc') { processedComponents.sort((a, b) => Number(a.price) - Number(b.price)); } else if (sortOrder === 'price_desc') { processedComponents.sort((a, b) => Number(b.price) - Number(a.price)); } const handleBrandChange = (event: any) => { const value = event.target.value; setSelectedBrands(typeof value === 'string' ? value.split(',') : value); }; const activeFiltersCount = selectedBrands.length + (sortOrder !== 'default' ? 1 : 0); const FilterContent = React.useMemo(() => ( setTempSearchQuery(e.target.value)} sx={{mb: 2}} InputProps={{ startAdornment: , }} /> Sort By Brands Price Range setPriceRange(v as number[])} min={0} max={2000} sx={{color: '#ff8201'}}/> ${priceRange[0]} ${priceRange[1]}+ ), [tempSearchQuery, sortOrder, selectedBrands, availableBrands, priceRange]); if (!open) return null; return ( <> setMobileFiltersOpen(true)} sx={{ display: {xs: 'flex', md: 'none'}, mr: 2 }} > Browsing: { category === 'gpu' ? 'GRAPHICS CARDS' : category === 'memory_card' ? 'STORAGE EXPANSION CARDS' : category === 'power_supply' ? 'POWER SUPPLIES' : category === 'network_card' ? 'NETWORK CARDS' : category === 'network_adapters' ? 'NETWORK ADAPTERS' : category === 'sound_card' ? 'SOUND CARDS' : category === 'optical_drive' ? 'OPTICAL DRIVES' : category?.toUpperCase()} {mode === 'forge' && currentBuildId && ( COMPATIBILITY MODE )} {FilterContent} {loading ? ( ) : ( {processedComponents.map((comp) => ( {comp.brand} {comp.name} {formatMoney(comp.price)} {mode === 'forge' && onSelect && ( )} ))} {processedComponents.length === 0 && ( No compatible components found. {mode === 'forge' && ( (Try removing incompatible parts) )} )} )} setSelectedComponent(null)} /> setMobileFiltersOpen(false)} sx={{zIndex: 1400}} PaperProps={{ sx: { bgcolor: '#1e1e1e' } }} disableScrollLock={true} > Filters setMobileFiltersOpen(false)}> {FilterContent} setSuggestOpen(false)} maxWidth="sm" fullWidth> Suggest a New Component Category: {category?.toUpperCase()} setSnackbarOpen(false)} anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} > setSnackbarOpen(false)} sx={{width: '100%'}}> {snackbarMessage} ); }