Changes in / [a744c90:e03e6fb]


Ignore:
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • components/AddComponentDialog.tsx

    ra744c90 re03e6fb  
    2020];
    2121
    22 export default function AddComponentDialog({ open, onClose, onSuccess, prefillData }: {
     22export default function AddComponentDialog({ open, onClose, onSuccess }: {
    2323    open: boolean;
    2424    onClose: () => void;
    2525    onSuccess: () => void;
    26     prefillData?: {
    27         type?: string;
    28         suggestionLink?: string;
    29         suggestionDescription?: string;
    30     };
    3126}) {
    3227    const [name, setName] = useState('');
     
    7368        }
    7469    }, [type]);
    75 
    76     useEffect(() => {
    77         if (open && prefillData) {
    78             if (prefillData.type) setType(prefillData.type);
    79         }
    80     }, [open, prefillData]);
    8170
    8271    const handleFieldChange = (fieldName: string, value: any) => {
  • components/ComponentDialog.tsx

    ra744c90 re03e6fb  
    4040
    4141    useEffect(() => {
    42         if (open && category) {
    43             setSuggestForm({
    44                 link: '',
    45                 description: '',
    46                 componentType: category
    47             });
    48         }
    49     }, [open, category]);
    50 
    51     useEffect(() => {
    5242        const timeoutId = setTimeout(() => {
    5343            setSearchQuery(tempSearchQuery);
     
    5646    }, [tempSearchQuery]);
    5747
     48    // Load user auth
    5849    useEffect(() => {
    5950        if (open) {
     
    10697            [e.target.name]: e.target.value
    10798        });
    108     }
    109 
    110 
     99    };
    111100
    112101    const submitSuggestion = async () => {
  • components/Navbar.tsx

    ra744c90 re03e6fb  
    77import Menu from "@mui/material/Menu";
    88import MenuItem from "@mui/material/MenuItem";
    9 import IconButton from "@mui/material/IconButton";
    10 import Drawer from "@mui/material/Drawer";
    11 import List from "@mui/material/List";
    12 import ListItem from "@mui/material/ListItem";
    13 import ListItemButton from "@mui/material/ListItemButton";
    14 import ListItemIcon from "@mui/material/ListItemIcon";
    15 import ListItemText from "@mui/material/ListItemText";
    16 import Divider from "@mui/material/Divider";
    17 import Collapse from "@mui/material/Collapse";
    18 
    199import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
    20 import MenuIcon from '@mui/icons-material/Menu';
    21 import CloseIcon from '@mui/icons-material/Close';
    22 import BuildIcon from '@mui/icons-material/Build';
    23 import ViewListIcon from '@mui/icons-material/ViewList';
    24 import ExpandLess from '@mui/icons-material/ExpandLess';
    25 import ExpandMore from '@mui/icons-material/ExpandMore';
    26 import PersonIcon from '@mui/icons-material/Person';
    27 import LogoutIcon from '@mui/icons-material/Logout';
    28 import LoginIcon from '@mui/icons-material/Login';
    29 import PersonAddIcon from '@mui/icons-material/PersonAdd';
    30 
    3110import {
    32     Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions
     11    Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, ListItemText
    3312} from "@mui/material";
    3413
     
    6039    { id: 'power_supply', label: 'Power Supplies', icon: <StorageIcon fontSize="small" /> },
    6140    { id: 'cooler', label: 'Cooling', icon: <StorageIcon fontSize="small" /> },
     41
     42    // Peripherals / Accessories (Missing ones)
    6243    { id: 'network_adapter', label: 'Network Adapters (WiFi)', icon: <RouterIcon fontSize="small" /> },
    6344    { id: 'network_card', label: 'Network Cards (Ethernet)', icon: <LanIcon fontSize="small" /> },
     
    6849];
    6950
     51
    7052export default function Navbar() {
    7153    const [auth, setAuth] = useState<AuthState | null>(null);
    7254    const [openLogoutDialog, setOpenLogoutDialog] = useState(false);
    73     const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false);
    74     const [mobileComponentsOpen, setMobileComponentsOpen] = useState(false);
    7555
    7656    const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
     
    9272        setBrowserOpen(true);
    9373        handleMenuClose();
    94         setMobileDrawerOpen(false);
    95         setMobileComponentsOpen(false);
    9674    };
    9775
     
    9977        e.preventDefault();
    10078        setOpenLogoutDialog(true);
    101         setMobileDrawerOpen(false);
    10279    };
    10380
     
    137114            <AppBar position="static" color="default" enableColorOnDark>
    138115                <Toolbar>
    139                     <Box sx={{ display: 'flex', alignItems: 'center', mr: { xs: 1, md: 4 } }}>
    140                         <Box
    141                             component="img"
    142                             src={LogoUrl}
    143                             alt="PC Forge Logo"
    144                             sx={{ height: 40, mr: { xs: 1, md: 2 }, cursor: 'pointer' }}
    145                             onClick={() => window.location.href='/'}
    146                         />
    147                         <Typography
    148                             variant="h6"
    149                             component="a"
    150                             href="/"
    151                             sx={{
    152                                 textDecoration: "none",
    153                                 color: "inherit",
    154                                 fontWeight: "bold",
    155                                 display: { xs: 'none', sm: 'block' }
    156                             }}
    157                         >
     116                    <Box sx={{ display: 'flex', alignItems: 'center', mr: 4 }}>
     117                        <Box component="img" src={LogoUrl} alt="PC Forge Logo" sx={{ height: 40, mr: 2, cursor: 'pointer' }} onClick={() => window.location.href='/'} />
     118                        <Typography variant="h6" component="a" href="/" sx={{ textDecoration: "none", color: "inherit", fontWeight: "bold" }}>
    158119                            PC Forge
    159120                        </Typography>
     
    179140                            {COMPONENT_CATEGORIES.map((cat) => (
    180141                                <MenuItem key={cat.id} onClick={() => handleCategorySelect(cat.id)}>
    181                                     <ListItemIcon>{cat.icon}</ListItemIcon>
     142                                    {/*<ListItemIcon>{cat.icon}</ListItemIcon>*/}
    182143                                    <ListItemText>{cat.label}</ListItemText>
    183144                                </MenuItem>
     
    190151                    <Box sx={{ flexGrow: 1 }} />
    191152
    192                     <Box sx={{ display: { xs: 'none', md: 'flex' }, gap: 1 }}>
     153                    <Box sx={{ display: 'flex', gap: 1 }}>
    193154                        {auth?.isLoggedIn ? (
    194155                            <>
     
    198159                        ) : (
    199160                            <>
    200                                 <Button color="inherit" href="/auth/login" sx={onHoverNav}>Login</Button>
    201                                 <Button color="inherit" href="/auth/register" sx={onHoverNav}>Register</Button>
     161                                <Button color="inherit" href="/auth/login">Login</Button>
     162                                <Button color="inherit" href="/auth/register">Register</Button>
    202163                            </>
    203164                        )}
    204165                    </Box>
    205 
    206                     <IconButton
    207                         color="inherit"
    208                         edge="end"
    209                         onClick={() => setMobileDrawerOpen(true)}
    210                         sx={{ display: { xs: 'block', md: 'none' } }}
    211                     >
    212                         <MenuIcon />
    213                     </IconButton>
    214166                </Toolbar>
    215167            </AppBar>
    216 
    217             <Drawer
    218                 anchor="right"
    219                 open={mobileDrawerOpen}
    220                 onClose={() => setMobileDrawerOpen(false)}
    221                 sx={{
    222                     display: { xs: 'block', md: 'none' },
    223                     '& .MuiDrawer-paper': { width: 280 , height: '60%'}
    224                 }}
    225             >
    226                 <Box sx={{ p: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
    227                     <Typography variant="h6" fontWeight="bold">Menu</Typography>
    228                     <IconButton onClick={() => setMobileDrawerOpen(false)}>
    229                         <CloseIcon />
    230                     </IconButton>
    231                 </Box>
    232                 <Divider />
    233 
    234                 <List>
    235                     <ListItem disablePadding>
    236                         <ListItemButton onClick={() => { window.location.href = '/forge'; }}>
    237                             <ListItemIcon><BuildIcon /></ListItemIcon>
    238                             <ListItemText primary="Forge" />
    239                         </ListItemButton>
    240                     </ListItem>
    241 
    242                     <ListItem disablePadding>
    243                         <ListItemButton onClick={() => setMobileComponentsOpen(!mobileComponentsOpen)}>
    244                             <ListItemIcon><ViewListIcon /></ListItemIcon>
    245                             <ListItemText primary="Components" />
    246                             {mobileComponentsOpen ? <ExpandLess /> : <ExpandMore />}
    247                         </ListItemButton>
    248                     </ListItem>
    249                     <Collapse in={mobileComponentsOpen} timeout="auto" unmountOnExit>
    250                         <List component="div" disablePadding>
    251                             {COMPONENT_CATEGORIES.map((cat) => (
    252                                 <ListItemButton
    253                                     key={cat.id}
    254                                     sx={{ pl: 4 }}
    255                                     onClick={() => handleCategorySelect(cat.id)}
    256                                 >
    257                                     <ListItemIcon>{cat.icon}</ListItemIcon>
    258                                     <ListItemText primary={cat.label} />
    259                                 </ListItemButton>
    260                             ))}
    261                         </List>
    262                     </Collapse>
    263 
    264                     <ListItem disablePadding>
    265                         <ListItemButton onClick={() => { window.location.href = '/completed-builds'; }}>
    266                             <ListItemIcon><ViewListIcon /></ListItemIcon>
    267                             <ListItemText primary="Completed Builds" />
    268                         </ListItemButton>
    269                     </ListItem>
    270 
    271                     <Divider sx={{ my: 1 }} />
    272 
    273                     {auth?.isLoggedIn ? (
    274                         <>
    275                             <ListItem disablePadding>
    276                                 <ListItemButton onClick={() => { window.location.href = checkDashboardUrl; }}>
    277                                     <ListItemIcon><PersonIcon /></ListItemIcon>
    278                                     <ListItemText primary={"My Profile"} />
    279                                 </ListItemButton>
    280                             </ListItem>
    281                             <ListItem disablePadding>
    282                                 <ListItemButton onClick={handleLogoutClick}>
    283                                     <ListItemIcon><LogoutIcon /></ListItemIcon>
    284                                     <ListItemText primary="Logout" />
    285                                 </ListItemButton>
    286                             </ListItem>
    287                         </>
    288                     ) : (
    289                         <>
    290                             <ListItem disablePadding>
    291                                 <ListItemButton onClick={() => { window.location.href = '/auth/login'; }}>
    292                                     <ListItemIcon><LoginIcon /></ListItemIcon>
    293                                     <ListItemText primary="Login" />
    294                                 </ListItemButton>
    295                             </ListItem>
    296                             <ListItem disablePadding>
    297                                 <ListItemButton onClick={() => { window.location.href = '/auth/register'; }}>
    298                                     <ListItemIcon><PersonAddIcon /></ListItemIcon>
    299                                     <ListItemText primary="Register" />
    300                                 </ListItemButton>
    301                             </ListItem>
    302                         </>
    303                     )}
    304                 </List>
    305             </Drawer>
    306168
    307169            <Dialog open={openLogoutDialog} onClose={() => setOpenLogoutDialog(false)}>
  • pages/dashboard/admin/+Page.tsx

    ra744c90 re03e6fb  
    5151    const [adminComment, setAdminComment] = useState("");
    5252
    53     const [createComponentDialog, setCreateComponentDialog] = useState<{
    54         open: boolean;
    55         suggestion: any | null;
    56     }>({open: false, suggestion: null});
    57 
    5853    const loadData = () => {
    5954        setLoading(true);
     
    148143    if (loading) {
    149144        return (
    150             <Container maxWidth="xl" sx={{
    151                 mt: 4,
    152                 mb: 10,
    153                 display: 'flex',
    154                 justifyContent: 'center',
    155                 alignItems: 'center',
    156                 minHeight: '50vh'
    157             }}>
    158                 <CircularProgress/>
     145            <Container maxWidth="xl" sx={{mt: 4, mb: 10, display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '50vh'}}>
     146                <CircularProgress />
    159147            </Container>
    160148        );
     
    208196                                size="large"
    209197                                fullWidth
    210                                 startIcon={<BuildIcon/>}
     198                                startIcon={<BuildIcon />}
    211199                                onClick={() => setAddDialogOpen(true)}
    212                                 sx={{mb: 2}}
     200                                sx={{ mb: 2 }}
    213201                            >
    214202                                Add Component
     
    225213                                    <MemoryIcon color="secondary" sx={{mr: 1}}/>
    226214                                    <Typography variant="h6" fontWeight="bold">
    227                                         Component Suggestions ({data.componentSuggestions?.length || 0})
     215                                        Suggested Components ({data.componentSuggestions?.length || 0})
    228216                                    </Typography>
    229217                                </Box>
    230218
    231219                                {data.componentSuggestions?.length === 0 ? (
    232                                     <Typography color="text.secondary">No suggestions.</Typography>
     220                                    <Typography color="text.secondary">No pending suggestions.</Typography>
    233221                                ) : (
    234222                                    <Table size="small">
     
    238226                                                <TableCell>Type</TableCell>
    239227                                                <TableCell>User</TableCell>
    240                                                 <TableCell>Status</TableCell>
    241228                                                <TableCell align="right">Actions</TableCell>
    242229                                            </TableRow>
     
    258245                                                    <TableCell>{sug.componentType?.toUpperCase()}</TableCell>
    259246                                                    <TableCell>{sug.userId}</TableCell>
    260                                                     <TableCell>
    261                                                         <Chip
    262                                                             label={sug.status || 'pending'}
     247                                                    <TableCell align="right">
     248                                                        <IconButton
    263249                                                            size="small"
    264                                                             color={
    265                                                                 sug.status === 'approved' ? 'success' :
    266                                                                     sug.status === 'rejected' ? 'error' :
    267                                                                         'default'
    268                                                             }
    269                                                         />
    270                                                     </TableCell>
    271                                                     <TableCell align="right">
    272                                                         {sug.status === 'pending' ? (
    273                                                             <>
    274                                                                 <IconButton
    275                                                                     size="small"
    276                                                                     color="success"
    277                                                                     onClick={() => openSuggestionReview(sug.id, 'approved')}
    278                                                                 >
    279                                                                     <CheckCircleIcon/>
    280                                                                 </IconButton>
    281                                                                 <IconButton
    282                                                                     size="small"
    283                                                                     color="error"
    284                                                                     onClick={() => openSuggestionReview(sug.id, 'rejected')}
    285                                                                 >
    286                                                                     <CancelIcon/>
    287                                                                 </IconButton>
    288                                                             </>
    289                                                         ) : sug.status === 'approved' ? (
    290                                                             <Button
    291                                                                 size="small"
    292                                                                 variant="contained"
    293                                                                 color="warning"
    294                                                                 startIcon={<AddIcon/>}
    295                                                                 onClick={() => setCreateComponentDialog({
    296                                                                     open: true,
    297                                                                     suggestion: sug
    298                                                                 })}
    299                                                             >
    300                                                                 Create
    301                                                             </Button>
    302                                                         ) : (
    303                                                             <Typography variant="caption" color="text.secondary">
    304                                                                 {sug.adminComment || 'Rejected'}
    305                                                             </Typography>
    306                                                         )}
     250                                                            color="success"
     251                                                            onClick={() => openSuggestionReview(sug.id, 'approved')}
     252                                                        >
     253                                                            <CheckCircleIcon/>
     254                                                        </IconButton>
     255                                                        <IconButton
     256                                                            size="small"
     257                                                            color="error"
     258                                                            onClick={() => openSuggestionReview(sug.id, 'rejected')}
     259                                                        >
     260                                                            <CancelIcon/>
     261                                                        </IconButton>
    307262                                                    </TableCell>
    308263                                                </TableRow>
     
    344299                                                            color="warning"
    345300                                                            size="small"
    346                                                             startIcon={<BuildIcon/>}
     301                                                            startIcon={<BuildIcon />}
    347302                                                            onClick={(e) => {
    348303                                                                e.stopPropagation();
     
    382337                                                            color="error"
    383338                                                            size="small"
    384                                                             startIcon={<DeleteIcon/>}
     339                                                            startIcon={<DeleteIcon />}
    385340                                                            onClick={(e) => {
    386341                                                                e.stopPropagation();
     
    403358            </Grid>
    404359
    405             <Dialog open={suggestionDialog.open}
    406                     onClose={() => setSuggestionDialog({...suggestionDialog, open: false})}>
     360            <Dialog open={suggestionDialog.open} onClose={() => setSuggestionDialog({...suggestionDialog, open: false})}>
    407361                <DialogTitle>Review Component Suggestion</DialogTitle>
    408362                <DialogContent>
     
    415369                        value={adminComment}
    416370                        onChange={(e) => setAdminComment(e.target.value)}
    417                         sx={{mt: 2}}
     371                        sx={{ mt: 2 }}
    418372                    />
    419373                </DialogContent>
     
    494448                        color="error"
    495449                        disabled={deleteLoading}
    496                         startIcon={deleteLoading ? <CircularProgress size={20}/> : <DeleteIcon/>}
     450                        startIcon={deleteLoading ? <CircularProgress size={20}/> : <DeleteIcon />}
    497451                    >
    498452                        {deleteLoading ? 'Deleting...' : 'Delete Build'}
     
    517471                }}
    518472            />
    519 
    520             <AddComponentDialog
    521                 open={createComponentDialog.open}
    522                 onClose={() => setCreateComponentDialog({ open: false, suggestion: null })}
    523                 onSuccess={() => {
    524                     loadData();
    525                     setCreateComponentDialog({ open: false, suggestion: null });
    526                 }}
    527                 prefillData={createComponentDialog.suggestion ? {
    528                     type: createComponentDialog.suggestion.componentType,
    529                     suggestionLink: createComponentDialog.suggestion.link,
    530                     suggestionDescription: createComponentDialog.suggestion.description
    531                 } : undefined}
    532             />
    533473        </Container>
    534474    );
Note: See TracChangeset for help on using the changeset viewer.