Ignore:
Timestamp:
01/28/26 21:15:38 (5 months ago)
Author:
Mihail <mihail2.naumov@…>
Branches:
main
Children:
adc31ef
Parents:
1d8f088
Message:

Fixed specs displaying in the forge page and some scaling issues.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • components/ComponentDialog.tsx

    r1d8f088 r1b5c18b  
    11import React, {useEffect, useState} from 'react';
    22import {
    3     Dialog, DialogContent, IconButton, Box, Typography, Chip,
     3    Dialog, DialogContent, IconButton, Box, Typography,
    44    Slider, FormControl, InputLabel, Select, MenuItem, Checkbox, ListItemText,
    55    Card, CardContent, CardMedia, Button, CircularProgress, AppBar, Toolbar, InputAdornment, TextField,
    6     TextField as MuiTextField, DialogTitle, DialogActions, Snackbar, Alert
     6    TextField as MuiTextField, DialogTitle, DialogActions, Snackbar, Alert, Drawer, Badge
    77} from '@mui/material';
    88import CloseIcon from '@mui/icons-material/Close';
    99import AddCircleIcon from '@mui/icons-material/AddCircle';
     10import FilterListIcon from '@mui/icons-material/FilterList';
     11import SearchIcon from "@mui/icons-material/Search";
    1012
    1113import {onGetAllComponents, onGetAuthState, onSuggestComponent} from '../pages/+Layout.telefunc'
    1214import {onGetCompatibleComponents} from '../pages/forge/forge.telefunc';
    1315import ComponentDetailsDialog from "./ComponentDetailsDialog";
    14 import SearchIcon from "@mui/icons-material/Search";
    1516
    1617const formatMoney = (amount: number) => `$${Number(amount).toFixed(2)}`;
     
    3839    const [snackbarMessage, setSnackbarMessage] = useState("");
    3940    const [userId, setUserId] = useState<number | null>(null);
     41    const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
    4042
    4143    useEffect(() => {
     
    108110    }
    109111
    110 
    111 
    112112    const submitSuggestion = async () => {
    113113        if (!userId) {
     
    165165    };
    166166
     167    const activeFiltersCount = selectedBrands.length + (sortOrder !== 'default' ? 1 : 0);
     168
     169    const FilterContent = React.useMemo(() => (
     170        <Box sx={{width: {xs: 280, md: 300}, p: 3, bgcolor: 'transparent'}}>
     171            <TextField
     172                fullWidth
     173                size="small"
     174                placeholder="Search components..."
     175                value={tempSearchQuery}
     176                onChange={(e) => setTempSearchQuery(e.target.value)}
     177                sx={{mb: 2}}
     178                InputProps={{
     179                    startAdornment: <InputAdornment position="start"><SearchIcon/></InputAdornment>,
     180                }}
     181            />
     182
     183            <FormControl fullWidth size="small" sx={{mb: 2}}>
     184                <InputLabel>Sort By</InputLabel>
     185                <Select
     186                    value={sortOrder}
     187                    label="Sort By"
     188                    onChange={(e) => setSortOrder(e.target.value)}
     189                    MenuProps={{
     190                        container: typeof window !== 'undefined' ? document.body : undefined,
     191                        disablePortal: false,
     192                        sx: {
     193                            zIndex: 1500
     194                        }
     195                    }}
     196                >
     197                    <MenuItem value="price_asc">Price: Low to High</MenuItem>
     198                    <MenuItem value="price_desc">Price: High to Low</MenuItem>
     199                </Select>
     200            </FormControl>
     201
     202            <FormControl fullWidth size="small" sx={{mb: 2}}>
     203                <InputLabel>Brands</InputLabel>
     204                <Select
     205                    multiple
     206                    value={selectedBrands}
     207                    onChange={handleBrandChange}
     208                    label="Brands"
     209                    renderValue={(s) => s.join(', ')}
     210                    MenuProps={{
     211                        container: typeof window !== 'undefined' ? document.body : undefined,
     212                        disablePortal: false,
     213                        sx: {
     214                            zIndex: 1500
     215                        },
     216                        PaperProps: {
     217                            sx: {
     218                                maxHeight: 300
     219                            }
     220                        }
     221                    }}
     222                >
     223                    {availableBrands.map((brand) => (
     224                        <MenuItem key={brand} value={brand}>
     225                            <Checkbox checked={selectedBrands.indexOf(brand) > -1}/>
     226                            <ListItemText primary={brand}/>
     227                        </MenuItem>
     228                    ))}
     229                </Select>
     230            </FormControl>
     231
     232            <Typography gutterBottom fontWeight="bold">Price Range</Typography>
     233            <Slider value={priceRange} onChange={(_, v) => setPriceRange(v as number[])} min={0} max={2000}
     234                    sx={{color: '#ff8201'}}/>
     235            <Box sx={{display: 'flex', justifyContent: 'space-between', mt: 1}}>
     236                <Typography variant="caption">${priceRange[0]}</Typography>
     237                <Typography variant="caption">${priceRange[1]}+</Typography>
     238            </Box>
     239
     240            <Button
     241                fullWidth
     242                variant="contained"
     243                startIcon={<AddCircleIcon/>}
     244                onClick={() => setSuggestOpen(true)}
     245                sx={{
     246                    mt: 2,
     247                    bgcolor: '#ff8201',
     248                    fontWeight: 'bold',
     249                    fontSize: '0.875rem',
     250                    '&:hover': {bgcolor: '#e67300'}
     251                }}
     252            >
     253                Suggest Component
     254            </Button>
     255        </Box>
     256    ), [tempSearchQuery, sortOrder, selectedBrands, availableBrands, priceRange]);
     257
    167258    if (!open) return null;
    168259
    169260    return (
    170261        <>
    171             <Dialog open={open} onClose={onClose} maxWidth="xl" fullWidth sx={{height: '90vh'}}>
     262            <Dialog
     263                open={open}
     264                onClose={onClose}
     265                maxWidth="xl"
     266                fullWidth
     267                fullScreen
     268                sx={{
     269                    '& .MuiDialog-paper': {
     270                        height: {xs: '100%', md: '90vh'},
     271                        m: {xs: 0, md: 2}
     272                    }
     273                }}
     274            >
    172275                <AppBar position="relative" sx={{bgcolor: '#ff8201'}}>
    173276                    <Toolbar>
    174                         <Typography sx={{ml: 2, flex: 1, textTransform: 'capitalize'}} variant="h6" component="div">
    175                             Browsing: <b>{category === 'gpu' ? 'Graphics Cards' : category?.toUpperCase()}</b>
     277                        <IconButton
     278                            edge="start"
     279                            color="inherit"
     280                            onClick={() => setMobileFiltersOpen(true)}
     281                            sx={{
     282                                display: {xs: 'flex', md: 'none'},
     283                                mr: 2
     284                            }}
     285                        >
     286                            <Badge badgeContent={activeFiltersCount} color="error">
     287                                <FilterListIcon/>
     288                            </Badge>
     289                        </IconButton>
     290
     291                        <Typography
     292                            sx={{ml: {xs: 0, md: 2}, flex: 1, fontSize: {xs: '1rem', sm: '1.25rem'}}}
     293                            variant="h6"
     294                            component="div"
     295                        >
     296                            <Box component="span" sx={{display: {xs: 'none', sm: 'inline'}}}>
     297                                Browsing:
     298                            </Box>
     299                            <b> {category === 'gpu' ? 'Graphics Cards' : category?.toUpperCase()}</b>
    176300                            {mode === 'forge' && currentBuildId && (
    177                                 <Typography variant="caption"
    178                                             sx={{ml: 2, bgcolor: 'rgba(0,0,0,0.2)', px: 1, borderRadius: 1}}>
    179                                     COMPATIBILITY MODE ON
     301                                <Typography
     302                                    variant="caption"
     303                                    sx={{
     304                                        ml: {xs: 1, sm: 2},
     305                                        bgcolor: 'rgba(0,0,0,0.2)',
     306                                        px: 1,
     307                                        py: 0.5,
     308                                        borderRadius: 1,
     309                                        display: {xs: 'none', sm: 'inline-block'}
     310                                    }}
     311                                >
     312                                    COMPATIBILITY MODE
    180313                                </Typography>
    181314                            )}
    182315                        </Typography>
    183                         <IconButton edge="start" color="inherit" onClick={onClose}>
     316                        <IconButton edge="end" color="inherit" onClick={onClose}>
    184317                            <CloseIcon/>
    185318                        </IconButton>
     
    187320                </AppBar>
    188321
    189                 <DialogContent sx={{p: 0, display: 'flex', height: '100%'}}>
     322                <DialogContent sx={{p: 0, display: 'flex', height: '100%', overflow: 'hidden'}}>
    190323                    <Box sx={{
    191                         width: 300,
     324                        display: {xs: 'none', md: 'block'},
    192325                        borderRight: '1px solid #ddd',
    193                         p: 3,
    194                         bgcolor: '#1e1e1e',
    195                         display: {xs: 'none', md: 'block'},
    196                         overflowY: 'auto'
     326                        overflowY: 'auto',
     327                        bgcolor: '#1e1e1e'
    197328                    }}>
    198                         <TextField
    199                             fullWidth
    200                             size="small"
    201                             placeholder="Search components..."
    202                             value={tempSearchQuery}
    203                             onChange={(e) => setTempSearchQuery(e.target.value)}
    204                             sx={{mb: 2}}
    205                             InputProps={{
    206                                 startAdornment: <InputAdornment position="start"><SearchIcon/></InputAdornment>,
    207                             }}
    208                         />
    209 
    210 
    211                         <FormControl fullWidth size="small" sx={{mb: 2}}>
    212                             <InputLabel>Sort By</InputLabel>
    213                             <Select value={sortOrder} label="Sort By" onChange={(e) => setSortOrder(e.target.value)}>
    214                                 <MenuItem value="price_asc">Price: Low to High</MenuItem>
    215                                 <MenuItem value="price_desc">Price: High to Low</MenuItem>
    216                             </Select>
    217                         </FormControl>
    218 
    219                         <FormControl fullWidth size="small" sx={{mb: 2}}>
    220                             <InputLabel>Brands</InputLabel>
    221                             <Select multiple value={selectedBrands} onChange={handleBrandChange} label="Brands"
    222                                     renderValue={(s) => s.join(', ')}>
    223                                 {availableBrands.map((brand) => (
    224                                     <MenuItem key={brand} value={brand}>
    225                                         <Checkbox checked={selectedBrands.indexOf(brand) > -1}/>
    226                                         <ListItemText primary={brand}/>
    227                                     </MenuItem>
    228                                 ))}
    229                             </Select>
    230                         </FormControl>
    231 
    232                         <Typography gutterBottom fontWeight="bold">Price Range</Typography>
    233                         <Slider value={priceRange} onChange={(_, v) => setPriceRange(v as number[])} min={0} max={2000}
    234                                 sx={{color: '#ff8201'}}/>
    235                         <Box sx={{display: 'flex', justifyContent: 'space-between', mt: 1}}>
    236                             <Typography variant="caption">${priceRange[0]}</Typography>
    237                             <Typography variant="caption">${priceRange[1]}+</Typography>
    238                         </Box>
    239                         {/*TO BE FINISHED*/}
    240                         <Button
    241                             fullWidth
    242                             variant="contained"
    243                             startIcon={<AddCircleIcon/>}
    244                             onClick={() => setSuggestOpen(true)}
    245                             sx={{
    246                                 mt: 2,
    247                                 bgcolor: '#ff8201',
    248                                 fontWeight: 'bold',
    249                                 fontSize: '0.875rem',
    250                                 '&:hover': {bgcolor: '#e67300'}
    251                             }}
    252                         >
    253                             Suggest Component
    254                         </Button>
     329                        {FilterContent}
    255330                    </Box>
    256 
    257                     <Box sx={{flex: 1, p: 3, overflowY: 'auto', bgcolor: '#121212'}}>
     331                    <Box sx={{flex: 1, p: {xs: 1.5, sm: 2, md: 3}, overflowY: 'auto', bgcolor: '#121212'}}>
    258332                        {loading ? (
    259333                            <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}>
     
    266340                                    xs: '1fr',
    267341                                    sm: 'repeat(2, 1fr)',
    268                                     md: 'repeat(3, 1fr)',
    269                                     lg: 'repeat(4, 1fr)',
    270                                     xl: 'repeat(5, 1fr)'
     342                                    md: 'repeat(2, 1fr)',
     343                                    lg: 'repeat(3, 1fr)',
     344                                    xl: 'repeat(4, 1fr)'
    271345                                },
    272                                 gap: 3,
     346                                gap: {xs: 1.5, sm: 2, md: 3},
    273347                                width: '100%'
    274348                            }}>
     
    301375                                                        height: '100%',
    302376                                                        objectFit: 'contain',
    303                                                         p: 2
     377                                                        p: {xs: 1, sm: 2}
    304378                                                    }}
    305379                                                />
     
    310384                                                display: 'flex',
    311385                                                flexDirection: 'column',
    312                                                 justifyContent: 'space-between'
     386                                                justifyContent: 'space-between',
     387                                                p: {xs: 1.5, sm: 2}
    313388                                            }}>
    314389                                                <Box>
    315                                                     <Typography variant="caption" color="text.secondary"
    316                                                                 sx={{textTransform: 'uppercase', letterSpacing: 0.5}}>
     390                                                    <Typography
     391                                                        variant="caption"
     392                                                        color="text.secondary"
     393                                                        sx={{
     394                                                            textTransform: 'uppercase',
     395                                                            letterSpacing: 0.5,
     396                                                            fontSize: {xs: '0.65rem', sm: '0.75rem'}
     397                                                        }}
     398                                                    >
    317399                                                        {comp.brand}
    318400                                                    </Typography>
    319                                                     <Typography variant="subtitle1" fontWeight="bold" sx={{
    320                                                         lineHeight: 1.2,
    321                                                         mt: 0.5,
    322                                                         mb: 1,
    323                                                         overflow: 'hidden',
    324                                                         textOverflow: 'ellipsis',
    325                                                         display: '-webkit-box',
    326                                                         WebkitLineClamp: 2,
    327                                                         WebkitBoxOrient: 'vertical',
    328                                                         minHeight: '2.4em'
    329                                                     }}>
     401                                                    <Typography
     402                                                        variant="subtitle1"
     403                                                        fontWeight="bold"
     404                                                        sx={{
     405                                                            lineHeight: 1.2,
     406                                                            mt: 0.5,
     407                                                            mb: 1,
     408                                                            overflow: 'hidden',
     409                                                            textOverflow: 'ellipsis',
     410                                                            display: '-webkit-box',
     411                                                            WebkitLineClamp: 2,
     412                                                            WebkitBoxOrient: 'vertical',
     413                                                            minHeight: '2.4em',
     414                                                            fontSize: {xs: '0.875rem', sm: '1rem'}
     415                                                        }}
     416                                                    >
    330417                                                        {comp.name}
    331418                                                    </Typography>
    332419                                                </Box>
    333                                                 <Typography variant="h6" color="primary.main" fontWeight="bold">
     420                                                <Typography
     421                                                    variant="h6"
     422                                                    color="primary.main"
     423                                                    fontWeight="bold"
     424                                                    sx={{fontSize: {xs: '1rem', sm: '1.25rem'}}}
     425                                                >
    334426                                                    {formatMoney(comp.price)}
    335427                                                </Typography>
    336428                                            </CardContent>
    337429
    338                                             <Box sx={{p: 2, pt: 0, display: 'flex', flexDirection: 'column', gap: 1}}>
     430                                            <Box sx={{
     431                                                p: {xs: 1.5, sm: 2},
     432                                                pt: 0,
     433                                                display: 'flex',
     434                                                flexDirection: 'column',
     435                                                gap: 1
     436                                            }}>
    339437                                                <Button
    340438                                                    fullWidth
    341439                                                    variant="contained"
    342440                                                    onClick={() => setSelectedComponent(comp)}
     441                                                    size="small"
    343442                                                    sx={{
    344443                                                        bgcolor: '#ff8201',
    345444                                                        fontWeight: 'bold',
     445                                                        fontSize: {xs: '0.75rem', sm: '0.875rem'},
    346446                                                        '&:hover': {bgcolor: '#e67300'}
    347447                                                    }}
     
    354454                                                        variant="contained"
    355455                                                        onClick={() => onSelect(comp)}
     456                                                        size="small"
    356457                                                        sx={{
    357458                                                            bgcolor: '#4caf50',
    358459                                                            fontWeight: 'bold',
     460                                                            fontSize: {xs: '0.75rem', sm: '0.875rem'},
    359461                                                            '&:hover': {bgcolor: '#388e3c'}
    360462                                                        }}
     
    369471                                {processedComponents.length === 0 && (
    370472                                    <Box sx={{gridColumn: '1 / -1', width: '100%', textAlign: 'center', mt: 5}}>
    371                                         <Typography variant="h6" color="text.secondary">
     473                                        <Typography variant="h6" color="text.secondary"
     474                                                    sx={{fontSize: {xs: '1rem', sm: '1.25rem'}}}>
    372475                                            No compatible components found.
    373476                                        </Typography>
     
    390493                />
    391494            </Dialog>
     495
     496            <Drawer
     497                anchor="left"
     498                open={mobileFiltersOpen && open}
     499                onClose={() => setMobileFiltersOpen(false)}
     500                sx={{zIndex: 1400}}
     501                PaperProps={{
     502                    sx: {
     503                        bgcolor: '#1e1e1e'
     504                    }
     505                }}
     506                disableScrollLock={true}
     507            >
     508                <Box sx={{pt: 2, width: 280}}>
     509                    <Box sx={{
     510                        display: 'flex',
     511                        justifyContent: 'space-between',
     512                        alignItems: 'center',
     513                        px: 3,
     514                        pb: 2
     515                    }}>
     516                        <Typography variant="h6" fontWeight="bold">Filters</Typography>
     517                        <IconButton onClick={() => setMobileFiltersOpen(false)}>
     518                            <CloseIcon/>
     519                        </IconButton>
     520                    </Box>
     521                    {FilterContent}
     522                </Box>
     523            </Drawer>
    392524
    393525            <Dialog open={suggestOpen} onClose={() => setSuggestOpen(false)} maxWidth="sm" fullWidth>
Note: See TracChangeset for help on using the changeset viewer.