Changeset 546a194


Ignore:
Timestamp:
02/10/26 14:20:22 (5 months ago)
Author:
Mihail <mihail2.naumov@…>
Branches:
main
Children:
3a9c59c, 92fafb3
Parents:
f727252
Message:

Optimized sites (changed from deprecated Grid to Box+CSS Grid)

Location:
pages
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pages/completed-builds/+Page.tsx

    rf727252 r546a194  
    99import BuildCard from '../../components/BuildCard';
    1010import BuildDetailsDialog from '../../components/BuildDetailsDialog';
    11 import { onGetApprovedBuilds, onCloneBuild, onGetAuthState } from '../+Layout.telefunc';
     11import { onGetApprovedBuilds, onGetAuthState } from '../+Layout.telefunc';
    1212
    1313export default function CompletedBuildsPage() {
     
    6565
    6666    useEffect(() => {
    67         loadBuilds();
     67        void loadBuilds();
    6868    }, [sortBy, searchQuery]);
    69 
    70     const handleClone = async (buildId: number) => {
    71         if (!userId) return alert("Please login to clone builds!");
    72         if (confirm(`Clone this build?`)) {
    73             await onCloneBuild({buildId});
    74             alert("Build cloned!");
    75             setSelectedBuildId(null);
    76         }
    77     };
    7869
    7970    return (
     
    10293                            value={searchQuery}
    10394                            onChange={(e) => setSearchQuery(e.target.value)}
    104                             InputProps={{
    105                                 startAdornment: <InputAdornment position="start"><SearchIcon /></InputAdornment>,
     95                            slotProps={{
     96                                input: {
     97                                    startAdornment: <InputAdornment position="start"><SearchIcon /></InputAdornment>,
     98                                }
    10699                            }}
    107100                            sx={{ mb: 3 }}
     
    193186                currentUser={userId}
    194187                onClose={() => setSelectedBuildId(null)}
    195                 onClone={handleClone}
    196188            />
    197189        </Container>
  • pages/dashboard/admin/+Page.tsx

    rf727252 r546a194  
    11import React, {useEffect, useState} from 'react';
    22import {
    3     Container, Grid, Paper, Typography, Box, Avatar, Divider, Button,
     3    Container, Paper, Typography, Box, Avatar, Divider, Button,
    44    CircularProgress, Table, TableBody, TableCell, TableHead, TableRow,
    55    Chip, IconButton, TextField, Dialog, DialogTitle, DialogContent, DialogActions
     
    173173    return (
    174174        <Container maxWidth="xl" sx={{mt: 4, mb: 10}}>
    175             <Grid container spacing={4}>
    176                 <Grid item xs={12} md={3}>
     175            <Box sx={{
     176                display: 'grid',
     177                gridTemplateColumns: {
     178                    xs: '1fr',
     179                    md: '300px 1fr'
     180                },
     181                gap: 4
     182            }}>
     183                <Box>
    177184                    <Paper elevation={3} sx={{
    178185                        p: 4,
     
    216223                        </Box>
    217224                    </Paper>
    218                 </Grid>
    219 
    220                 <Grid item xs={12} md={9}>
    221                     <Grid container spacing={4} direction="column">
    222                         <Grid item xs={12}>
    223                             <Paper sx={{p: 3, borderLeft: '6px solid #9c27b0'}}>
    224                                 <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
    225                                     <MemoryIcon color="secondary" sx={{mr: 1}}/>
    226                                     <Typography variant="h6" fontWeight="bold">
    227                                         Component Suggestions ({data.componentSuggestions?.length || 0})
    228                                     </Typography>
    229                                 </Box>
    230 
    231                                 {data.componentSuggestions?.length === 0 ? (
    232                                     <Typography color="text.secondary">No suggestions.</Typography>
    233                                 ) : (
    234                                     <Table size="small">
    235                                         <TableHead>
    236                                             <TableRow>
    237                                                 <TableCell>Link/Description</TableCell>
    238                                                 <TableCell>Type</TableCell>
    239                                                 <TableCell>User</TableCell>
    240                                                 <TableCell>Status</TableCell>
    241                                                 <TableCell align="right">Actions</TableCell>
    242                                             </TableRow>
    243                                         </TableHead>
    244                                         <TableBody>
    245                                             {data.componentSuggestions?.map((sug: any) => (
    246                                                 <TableRow key={sug.id}>
    247                                                     <TableCell sx={{maxWidth: 300}}>
    248                                                         <a
    249                                                             href={sug.link}
    250                                                             target="_blank"
    251                                                             rel="noopener noreferrer"
    252                                                             title={sug.link}
    253                                                             style={{textDecoration: 'none', color: 'inherit'}}
    254                                                         >
    255                                                             {sug.description || sug.link}
    256                                                         </a>
    257                                                     </TableCell>
    258                                                     <TableCell>{sug.componentType?.toUpperCase()}</TableCell>
    259                                                     <TableCell>{sug.userId}</TableCell>
    260                                                     <TableCell>
    261                                                         <Chip
    262                                                             label={sug.status || 'pending'}
     225                </Box>
     226
     227                <Box sx={{
     228                    display: 'flex',
     229                    flexDirection: 'column',
     230                    gap: 4
     231                }}>
     232                    <Paper sx={{p: 3, borderLeft: '6px solid #9c27b0'}}>
     233                        <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
     234                            <MemoryIcon color="secondary" sx={{mr: 1}}/>
     235                            <Typography variant="h6" fontWeight="bold">
     236                                Component Suggestions ({data.componentSuggestions?.length || 0})
     237                            </Typography>
     238                        </Box>
     239
     240                        {data.componentSuggestions?.length === 0 ? (
     241                            <Typography color="text.secondary">No suggestions.</Typography>
     242                        ) : (
     243                            <Box sx={{width: '100%', overflowX: 'auto'}}>
     244                                <Table size="small">
     245                                    <TableHead>
     246                                        <TableRow>
     247                                            <TableCell>Link/Description</TableCell>
     248                                            <TableCell>Type</TableCell>
     249                                            <TableCell>User</TableCell>
     250                                            <TableCell>Status</TableCell>
     251                                            <TableCell align="right">Actions</TableCell>
     252                                        </TableRow>
     253                                    </TableHead>
     254                                    <TableBody>
     255                                        {data.componentSuggestions?.map((sug: any) => (
     256                                            <TableRow key={sug.id}>
     257                                                <TableCell sx={{minWidth: 200, maxWidth: 300}}>
     258                                                    <a
     259                                                        href={sug.link}
     260                                                        target="_blank"
     261                                                        rel="noopener noreferrer"
     262                                                        title={sug.link}
     263                                                        style={{textDecoration: 'none', color: 'inherit'}}
     264                                                    >
     265                                                        {sug.description || sug.link}
     266                                                    </a>
     267                                                </TableCell>
     268                                                <TableCell sx={{minWidth: 80}}>
     269                                                    {sug.componentType?.toUpperCase()}
     270                                                </TableCell>
     271                                                <TableCell sx={{minWidth: 100}}>
     272                                                    {sug.user?.username || `${sug.userId}`}
     273                                                </TableCell>
     274                                                <TableCell sx={{minWidth: 100}}>
     275                                                    <Chip
     276                                                        label={sug.status || 'pending'}
     277                                                        size="small"
     278                                                        color={
     279                                                            sug.status === 'approved' ? 'success' :
     280                                                                sug.status === 'rejected' ? 'error' :
     281                                                                    'default'
     282                                                        }
     283                                                    />
     284                                                </TableCell>
     285                                                <TableCell align="right" sx={{minWidth: 150}}>
     286                                                    {sug.status === 'pending' ? (
     287                                                        <>
     288                                                            <IconButton
     289                                                                size="small"
     290                                                                color="success"
     291                                                                onClick={() => openSuggestionReview(sug.id, 'approved')}
     292                                                            >
     293                                                                <CheckCircleIcon/>
     294                                                            </IconButton>
     295                                                            <IconButton
     296                                                                size="small"
     297                                                                color="error"
     298                                                                onClick={() => openSuggestionReview(sug.id, 'rejected')}
     299                                                            >
     300                                                                <CancelIcon/>
     301                                                            </IconButton>
     302                                                        </>
     303                                                    ) : sug.status === 'approved' ? (
     304                                                        <Button
    263305                                                            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                                                         )}
    307                                                     </TableCell>
    308                                                 </TableRow>
    309                                             ))}
    310                                         </TableBody>
    311                                     </Table>
    312                                 )}
    313                             </Paper>
    314                         </Grid>
    315 
    316                         <Grid item xs={12}>
    317                             <Paper sx={{p: 3, borderLeft: '6px solid #ed6c02', bgcolor: '#121212'}}>
    318                                 <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
    319                                     <BuildIcon color="warning" sx={{mr: 1}}/>
    320                                     <Typography variant="h6" fontWeight="bold">
    321                                         Builds Waiting for Approval ({data.pendingBuilds?.length || 0})
    322                                     </Typography>
    323                                 </Box>
    324 
    325                                 {data.pendingBuilds?.length === 0 ? (
    326                                     <Typography color="text.secondary">No pending builds.</Typography>
    327                                 ) : (
    328                                     <Grid container spacing={2}>
    329                                         {data.pendingBuilds.map((build: any) => (
    330                                             <Grid item xs={12} sm={6} md={4} lg={3} key={build.id}>
    331                                                 <Box sx={{position: 'relative'}}>
    332                                                     <BuildCard
    333                                                         build={build}
    334                                                         onClick={() => setSelectedBuildId(build.id)}
    335                                                     />
    336                                                     <Box sx={{
    337                                                         mt: 1,
    338                                                         display: 'flex',
    339                                                         gap: 1,
    340                                                         justifyContent: 'center'
    341                                                     }}>
    342                                                         <Button
    343306                                                            variant="contained"
    344307                                                            color="warning"
    345                                                             size="small"
    346                                                             startIcon={<BuildIcon/>}
    347                                                             onClick={(e) => {
    348                                                                 e.stopPropagation();
    349                                                                 openBuildApproval(build.id, build.name);
    350                                                             }}
     308                                                            startIcon={<AddIcon/>}
     309                                                            onClick={() => setCreateComponentDialog({
     310                                                                open: true,
     311                                                                suggestion: sug
     312                                                            })}
    351313                                                        >
    352                                                             Review
     314                                                            Create
    353315                                                        </Button>
    354                                                     </Box>
    355                                                 </Box>
    356                                             </Grid>
     316                                                    ) : (
     317                                                        <Typography variant="caption" color="text.secondary">
     318                                                            {sug.adminComment || 'Rejected'}
     319                                                        </Typography>
     320                                                    )}
     321                                                </TableCell>
     322                                            </TableRow>
    357323                                        ))}
    358                                     </Grid>
    359                                 )}
    360                             </Paper>
    361                         </Grid>
    362 
    363                         <Grid item xs={12}>
    364                             <Paper sx={{p: 3, borderLeft: '6px solid #2e7d32'}}>
    365                                 <Typography variant="h6" fontWeight="bold" gutterBottom>
    366                                     My Builds / Sandbox
    367                                 </Typography>
    368                                 {data.userBuilds?.length === 0 ? (
    369                                     <Typography color="text.secondary">No builds created by admin.</Typography>
    370                                 ) : (
    371                                     <Grid container spacing={2}>
    372                                         {data.userBuilds.slice(0, 4).map((build: any) => (
    373                                             <Grid item xs={12} sm={6} md={4} lg={3} key={build.id}>
    374                                                 <Box sx={{position: 'relative'}}>
    375                                                     <BuildCard
    376                                                         build={build}
    377                                                         onClick={() => setSelectedBuildId(build.id)}
    378                                                     />
    379                                                     <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}>
    380                                                         <Button
    381                                                             variant="outlined"
    382                                                             color="error"
    383                                                             size="small"
    384                                                             startIcon={<DeleteIcon/>}
    385                                                             onClick={(e) => {
    386                                                                 e.stopPropagation();
    387                                                                 openDeleteDialog(build.id, build.name);
    388                                                             }}
    389                                                             fullWidth
    390                                                         >
    391                                                             Delete
    392                                                         </Button>
    393                                                     </Box>
    394                                                 </Box>
    395                                             </Grid>
    396                                         ))}
    397                                     </Grid>
    398                                 )}
    399                             </Paper>
    400                         </Grid>
    401                     </Grid>
    402                 </Grid>
    403             </Grid>
     324                                    </TableBody>
     325                                </Table>
     326                            </Box>
     327                        )}
     328                    </Paper>
     329
     330                    <Paper sx={{p: 3, borderLeft: '6px solid #ed6c02', bgcolor: '#121212'}}>
     331                        <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
     332                            <BuildIcon color="warning" sx={{mr: 1}}/>
     333                            <Typography variant="h6" fontWeight="bold">
     334                                Builds Waiting for Approval ({data.pendingBuilds?.length || 0})
     335                            </Typography>
     336                        </Box>
     337
     338                        {data.pendingBuilds?.length === 0 ? (
     339                            <Typography color="text.secondary">No pending builds.</Typography>
     340                        ) : (
     341                            <Box sx={{
     342                                display: 'grid',
     343                                gridTemplateColumns: {
     344                                    xs: '1fr',
     345                                    sm: 'repeat(2, 1fr)',
     346                                    lg: 'repeat(3, 1fr)',
     347                                    xl: 'repeat(4, 1fr)'
     348                                },
     349                                gap: 2
     350                            }}>
     351                                {data.pendingBuilds.map((build: any) => (
     352                                    <Box key={build.id}>
     353                                        <BuildCard
     354                                            build={build}
     355                                            onClick={() => setSelectedBuildId(build.id)}
     356                                        />
     357                                        <Box sx={{mt: 1, display: 'flex', gap: 1, justifyContent: 'center'}}>
     358                                            <Button
     359                                                variant="contained"
     360                                                color="warning"
     361                                                size="small"
     362                                                startIcon={<BuildIcon/>}
     363                                                onClick={(e) => {
     364                                                    e.stopPropagation();
     365                                                    openBuildApproval(build.id, build.name);
     366                                                }}
     367                                            >
     368                                                Review
     369                                            </Button>
     370                                        </Box>
     371                                    </Box>
     372                                ))}
     373                            </Box>
     374                        )}
     375                    </Paper>
     376
     377                    <Paper sx={{p: 3, borderLeft: '6px solid #2e7d32'}}>
     378                        <Typography variant="h6" fontWeight="bold" gutterBottom>
     379                            My Builds / Sandbox
     380                        </Typography>
     381                        {data.userBuilds?.length === 0 ? (
     382                            <Typography color="text.secondary">No builds created by admin.</Typography>
     383                        ) : (
     384                            <Box sx={{
     385                                display: 'grid',
     386                                gridTemplateColumns: {
     387                                    xs: '1fr',
     388                                    sm: 'repeat(2, 1fr)',
     389                                    lg: 'repeat(3, 1fr)',
     390                                    xl: 'repeat(4, 1fr)'
     391                                },
     392                                gap: 2
     393                            }}>
     394                                {data.userBuilds.slice(0, 4).map((build: any) => (
     395                                    <Box key={build.id}>
     396                                        <BuildCard
     397                                            build={build}
     398                                            onClick={() => setSelectedBuildId(build.id)}
     399                                        />
     400                                        <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}>
     401                                            <Button
     402                                                variant="outlined"
     403                                                color="error"
     404                                                size="small"
     405                                                startIcon={<DeleteIcon/>}
     406                                                onClick={(e) => {
     407                                                    e.stopPropagation();
     408                                                    openDeleteDialog(build.id, build.name);
     409                                                }}
     410                                                fullWidth
     411                                            >
     412                                                Delete
     413                                            </Button>
     414                                        </Box>
     415                                    </Box>
     416                                ))}
     417                            </Box>
     418                        )}
     419                    </Paper>
     420                </Box>
     421            </Box>
    404422
    405423            <Dialog open={suggestionDialog.open}
     
    520538            <AddComponentDialog
    521539                open={createComponentDialog.open}
    522                 onClose={() => setCreateComponentDialog({ open: false, suggestion: null })}
     540                onClose={() => setCreateComponentDialog({open: false, suggestion: null})}
    523541                onSuccess={() => {
    524542                    loadData();
    525                     setCreateComponentDialog({ open: false, suggestion: null });
     543                    setCreateComponentDialog({open: false, suggestion: null});
    526544                }}
    527545                prefillData={createComponentDialog.suggestion ? {
  • pages/dashboard/user/+Page.tsx

    rf727252 r546a194  
    1010    CircularProgress,
    1111    IconButton,
    12     Grid,
    1312    Dialog,
    1413    DialogTitle,
     
    2423
    2524import {getUserInfoAndData, onDeleteBuild} from "./userDashboard.telefunc";
    26 import {onCloneBuild} from "../../+Layout.telefunc";
    2725
    2826import BuildCard from "../../../components/BuildCard";
     
    7270            await onDeleteBuild({buildId: deleteDialog.buildId});
    7371            setDeleteDialog({ open: false, buildId: null, buildName: '' });
    74             loadData(); // refresh na user i favorite builds
     72            loadData();
    7573            setSelectedBuildId(null);
    7674        } catch (e) {
     
    8179    };
    8280
    83     const handleCloneWrapper = async (buildId: number) => {
    84         if (!data?.user) return alert("Please login to clone builds!");
    85         if (confirm(`Clone this build to your dashboard?`)) {
    86             await onCloneBuild({buildId});
    87             alert("Build cloned! Check your dashboard.");
    88             setSelectedBuildId(null);
    89             loadData();
    90         }
    91     };
    92 
    9381    if (loading) return <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}><CircularProgress/></Box>;
    94     if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error"
    95                                                                                         variant="h6">{error}</Typography><Button
    96         href="/auth/login" variant="contained">Login</Button></Container>;
     82    if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error" variant="h6">{error}</Typography><Button href="/auth/login" variant="contained">Login</Button></Container>;
    9783
    9884    return (
    99         <Container maxWidth="xl" sx={{mt: 4, mb: 4, color: 'white'}}>
    100             <Grid container spacing={3}>
    101                 <Grid item xs={12} md={3}>
    102                     <Paper elevation={3}
    103                            sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}>
    104                         <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}><PersonIcon
    105                             sx={{fontSize: 60}}/></Avatar>
     85        <Container maxWidth="xl" sx={{mb: 4, color: 'white'}}>
     86            <Box sx={{
     87                display: 'grid',
     88                gridTemplateColumns: {
     89                    xs: '1fr',
     90                    md: '280px 1fr'
     91                },
     92                gap: 2
     93            }}>
     94                <Box>
     95                    <Paper elevation={3} sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}>
     96                        <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}>
     97                            <PersonIcon sx={{fontSize: 60}}/>
     98                        </Avatar>
    10699                        <Typography variant="h5" fontWeight="bold" gutterBottom>{data.user.username}</Typography>
    107100                        <Typography variant="body2" color="text.secondary" gutterBottom>{data.user.email}</Typography>
    108101                        <Divider sx={{width: '100%', my: 2}}/>
    109102                    </Paper>
    110                 </Grid>
    111 
    112                 <Grid item xs={12} md={9}>
    113                     <Grid container spacing={3} direction="column">
    114 
    115                         <Grid item xs={12}>
    116                             <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
    117                                 <Box sx={{
    118                                     display: 'flex',
    119                                     alignItems: 'center',
    120                                     justifyContent: 'space-between',
    121                                     mb: 2
    122                                 }}>
    123                                     <Box sx={{display: 'flex', alignItems: 'center'}}>
    124                                         <FavoriteIcon color="error" sx={{mr: 1}}/>
    125                                         <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography>
    126                                     </Box>
    127 
    128                                     {data.favoriteBuilds.length > 4 && (
     103                </Box>
     104
     105                <Box sx={{
     106                    display: 'flex',
     107                    flexDirection: 'column',
     108                    gap: 3
     109                }}>
     110                    <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
     111                        <Box sx={{
     112                            display: 'flex',
     113                            alignItems: 'center',
     114                            justifyContent: 'space-between',
     115                            mb: 2
     116                        }}>
     117                            <Box sx={{display: 'flex', alignItems: 'center'}}>
     118                                <FavoriteIcon color="error" sx={{mr: 1}}/>
     119                                <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography>
     120                            </Box>
     121
     122                            {data.favoriteBuilds.length > 6 && (
     123                                <Button
     124                                    variant="outlined"
     125                                    size="small"
     126                                    onClick={() => setOpenFavoritesDialog(true)}
     127                                >
     128                                    See All ({data.favoriteBuilds.length})
     129                                </Button>
     130                            )}
     131                        </Box>
     132                        <Divider sx={{mb: 2}}/>
     133
     134                        {data.favoriteBuilds.length === 0 ? (
     135                            <Typography color="text.secondary" align="center" sx={{mt: 4}}>
     136                                You haven't favorited any builds yet.
     137                            </Typography>
     138                        ) : (
     139                            <Box sx={{
     140                                display: 'grid',
     141                                gridTemplateColumns: {
     142                                    xs: '1fr',
     143                                    sm: 'repeat(2, 1fr)',
     144                                    md: 'repeat(3, 1fr)',
     145                                    lg: 'repeat(4, 1fr)',
     146                                    xl: 'repeat(6, 1fr)'
     147                                },
     148                                gap: 2
     149                            }}>
     150                                {data.favoriteBuilds.slice(0, 6).map((build: any) => (
     151                                    <BuildCard
     152                                        key={build.id}
     153                                        build={build}
     154                                        onClick={() => setSelectedBuildId(build.id)}
     155                                    />
     156                                ))}
     157                            </Box>
     158                        )}
     159                    </Paper>
     160
     161                    <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
     162                        <Box sx={{
     163                            display: 'flex',
     164                            alignItems: 'center',
     165                            justifyContent: 'space-between',
     166                            mb: 2
     167                        }}>
     168                            <Box sx={{display: 'flex', alignItems: 'center'}}>
     169                                <ComputerIcon color="primary" sx={{mr: 1}}/>
     170                                <Typography variant="h6" fontWeight="bold">My Builds</Typography>
     171                            </Box>
     172
     173                            {data.userBuilds.length > 6 && (
     174                                <Button
     175                                    variant="outlined"
     176                                    size="small"
     177                                    onClick={() => setOpenMyBuildsDialog(true)}
     178                                >
     179                                    See All ({data.userBuilds.length})
     180                                </Button>
     181                            )}
     182                        </Box>
     183                        <Divider sx={{mb: 2}}/>
     184
     185                        {data.userBuilds.length === 0 ? (
     186                            <Box sx={{textAlign: 'center', mt: 4}}>
     187                                <Typography color="text.secondary" gutterBottom>
     188                                    You haven't created any builds yet.
     189                                </Typography>
     190                                <Button variant="contained" href="/forge" sx={{color: 'white', fontWeight: 'bolder'}}>
     191                                    Start Forging
     192                                </Button>
     193                            </Box>
     194                        ) : (
     195                            <Box sx={{
     196                                display: 'grid',
     197                                gridTemplateColumns: {
     198                                    xs: '1fr',
     199                                    sm: 'repeat(2, 1fr)',
     200                                    md: 'repeat(3, 1fr)',
     201                                    lg: 'repeat(4, 1fr)',
     202                                    xl: 'repeat(6, 1fr)'
     203                                },
     204                                gap: 2
     205                            }}>
     206                                {data.userBuilds.slice(0, 6).map((build: any) => (
     207                                    <Box key={build.id} sx={{ display: 'flex', flexDirection: 'column' }}>
     208                                        <Box sx={{ flexGrow: 1 }}>
     209                                            <BuildCard
     210                                                build={build}
     211                                                onClick={() => setSelectedBuildId(build.id)}
     212                                            />
     213                                        </Box>
    129214                                        <Button
    130215                                            variant="outlined"
     216                                            color="error"
    131217                                            size="small"
    132                                             onClick={() => setOpenFavoritesDialog(true)}
     218                                            startIcon={<DeleteIcon/>}
     219                                            onClick={(e) => {
     220                                                e.stopPropagation();
     221                                                openDeleteDialog(build.id, build.name);
     222                                            }}
     223                                            sx={{ mt: 1, width: '100%' }}
    133224                                        >
    134                                             See All ({data.favoriteBuilds.length})
     225                                            Delete
    135226                                        </Button>
    136                                     )}
     227                                    </Box>
     228                                ))}
     229                            </Box>
     230                        )}
     231                    </Paper>
     232                </Box>
     233            </Box>
     234
     235            <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="xl" fullWidth>
     236                <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
     237                    All My Builds
     238                    <IconButton onClick={() => setOpenMyBuildsDialog(false)}>
     239                        <CloseIcon/>
     240                    </IconButton>
     241                </DialogTitle>
     242                <DialogContent dividers>
     243                    <Box sx={{
     244                        display: 'grid',
     245                        gridTemplateColumns: {
     246                            xs: '1fr',
     247                            sm: 'repeat(2, 1fr)',
     248                            md: 'repeat(3, 1fr)',
     249                            lg: 'repeat(4, 1fr)',
     250                            xl: 'repeat(5, 1fr)'
     251                        },
     252                        gap: 2,
     253                        mt: 1
     254                    }}>
     255                        {data.userBuilds.map((build: any) => (
     256                            <Box key={build.id}>
     257                                <BuildCard
     258                                    build={build}
     259                                    onClick={() => {
     260                                        setOpenMyBuildsDialog(false);
     261                                        setSelectedBuildId(build.id);
     262                                    }}
     263                                />
     264                                <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}>
     265                                    <Button
     266                                        variant="outlined"
     267                                        color="error"
     268                                        size="small"
     269                                        startIcon={<DeleteIcon/>}
     270                                        onClick={(e) => {
     271                                            e.stopPropagation();
     272                                            openDeleteDialog(build.id, build.name);
     273                                        }}
     274                                        sx={{width: '100%'}}
     275                                    >
     276                                        Delete
     277                                    </Button>
    137278                                </Box>
    138                                 <Divider sx={{mb: 2}}/>
    139 
    140                                 {data.favoriteBuilds.length === 0 ? (
    141                                     <Typography color="text.secondary" align="center" sx={{mt: 4}}>You haven't favorited
    142                                         any builds yet.</Typography>
    143                                 ) : (
    144                                     <Grid container spacing={2}>
    145                                         {data.favoriteBuilds.slice(0, 4).map((build: any) => (
    146                                             <Grid item xs={12} sm={6} md={4} key={build.id}>
    147                                                 <BuildCard
    148                                                     build={build}
    149                                                     onClick={() => setSelectedBuildId(build.id)}
    150                                                 />
    151                                             </Grid>
    152                                         ))}
    153                                     </Grid>
    154                                 )}
    155                             </Paper>
    156                         </Grid>
    157 
    158                         <Grid item xs={12}>
    159                             <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
    160                                 <Box sx={{
    161                                     display: 'flex',
    162                                     alignItems: 'center',
    163                                     justifyContent: 'space-between',
    164                                     mb: 2
    165                                 }}>
    166                                     <Box sx={{display: 'flex', alignItems: 'center'}}>
    167                                         <ComputerIcon color="primary" sx={{mr: 1}}/>
    168                                         <Typography variant="h6" fontWeight="bold">My Builds</Typography>
    169                                     </Box>
    170 
    171                                     {data.userBuilds.length > 4 && (
    172                                         <Button
    173                                             variant="outlined"
    174                                             size="small"
    175                                             onClick={() => setOpenMyBuildsDialog(true)}
    176                                         >
    177                                             See All ({data.userBuilds.length})
    178                                         </Button>
    179                                     )}
    180                                 </Box>
    181                                 <Divider sx={{mb: 2}}/>
    182 
    183                                 {data.userBuilds.length === 0 ? (
    184                                     <Box sx={{textAlign: 'center', mt: 4}}>
    185                                         <Typography color="text.secondary" gutterBottom>You haven't created any builds
    186                                             yet.</Typography>
    187                                         <Button variant="contained" href="/forge"
    188                                                 sx={{color: 'white', fontWeight: 'bolder'}}>Start Forging</Button>
    189                                     </Box>
    190                                 ) : (
    191                                     <Grid container spacing={2}>
    192                                         {data.userBuilds.slice(0, 4).map((build: any) => (
    193                                             <Grid item xs={12} sm={6} md={4} key={build.id}>
    194                                                 <Box sx={{ position: 'relative' }}>
    195                                                     <BuildCard
    196                                                         build={build}
    197                                                         onClick={() => setSelectedBuildId(build.id)}
    198                                                     />
    199                                                     <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
    200                                                         <Button
    201                                                             variant="outlined"
    202                                                             color="error"
    203                                                             size="small"
    204                                                             startIcon={<DeleteIcon />}
    205                                                             onClick={(e) => {
    206                                                                 e.stopPropagation();
    207                                                                 openDeleteDialog(build.id, build.name);
    208                                                             }}
    209                                                             sx={{ width: '100%' }}
    210                                                         >
    211                                                             Delete
    212                                                         </Button>
    213                                                     </Box>
    214                                                 </Box>
    215                                             </Grid>
    216                                         ))}
    217                                     </Grid>
    218                                 )}
    219                             </Paper>
    220                         </Grid>
    221 
    222                         <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="lg"
    223                                 fullWidth>
    224                             <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
    225                                 All My Builds
    226                                 <IconButton onClick={() => setOpenMyBuildsDialog(false)}>
    227                                     <CloseIcon/>
    228                                 </IconButton>
    229                             </DialogTitle>
    230                             <DialogContent dividers>
    231                                 <Grid container spacing={2} sx={{mt: 1}}>
    232                                     {data.userBuilds.map((build: any) => (
    233                                         <Grid item xs={12} sm={6} md={4} key={build.id}>
    234                                             <Box sx={{ position: 'relative' }}>
    235                                                 <BuildCard
    236                                                     build={build}
    237                                                     onClick={() => {
    238                                                         setOpenMyBuildsDialog(false);
    239                                                         setSelectedBuildId(build.id);
    240                                                     }}
    241                                                 />
    242                                                 <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
    243                                                     <Button
    244                                                         variant="outlined"
    245                                                         color="error"
    246                                                         size="small"
    247                                                         startIcon={<DeleteIcon />}
    248                                                         onClick={(e) => {
    249                                                             e.stopPropagation();
    250                                                             openDeleteDialog(build.id, build.name);
    251                                                         }}
    252                                                         sx={{ width: '100%' }}
    253                                                     >
    254                                                         Delete
    255                                                     </Button>
    256                                                 </Box>
    257                                             </Box>
    258                                         </Grid>
    259                                     ))}
    260                                 </Grid>
    261                             </DialogContent>
    262                             <DialogActions>
    263                                 <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button>
    264                             </DialogActions>
    265                         </Dialog>
    266 
    267                         <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="lg"
    268                                 fullWidth>
    269                             <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
    270                                 All Favorited Builds
    271                                 <IconButton onClick={() => setOpenFavoritesDialog(false)}>
    272                                     <CloseIcon/>
    273                                 </IconButton>
    274                             </DialogTitle>
    275                             <DialogContent dividers>
    276                                 <Grid container spacing={2} sx={{mt: 1}}>
    277                                     {data.favoriteBuilds.map((build: any) => (
    278                                         <Grid item xs={12} sm={6} md={4} key={build.id}>
    279                                             <BuildCard
    280                                                 build={build}
    281                                                 onClick={() => {
    282                                                     setOpenFavoritesDialog(false);
    283                                                     setSelectedBuildId(build.id);
    284                                                 }}
    285                                             />
    286                                         </Grid>
    287                                     ))}
    288                                 </Grid>
    289                             </DialogContent>
    290                             <DialogActions>
    291                                 <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button>
    292                             </DialogActions>
    293                         </Dialog>
    294 
    295                         <Dialog open={deleteDialog.open} onClose={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}>
    296                             <DialogTitle>Delete Build</DialogTitle>
    297                             <DialogContent>
    298                                 <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography>
    299                                 <Typography color="text.secondary">
    300                                     Are you sure you want to permanently delete this build? This action cannot be undone.
    301                                 </Typography>
    302                             </DialogContent>
    303                             <DialogActions>
    304                                 <Button
    305                                     onClick={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}
    306                                     disabled={deleteLoading}
    307                                 >
    308                                     Cancel
    309                                 </Button>
    310                                 <Button
    311                                     onClick={handleDelete}
    312                                     variant="contained"
    313                                     color="error"
    314                                     disabled={deleteLoading}
    315                                     startIcon={deleteLoading ? <CircularProgress size={20} /> : <DeleteIcon />}
    316                                 >
    317                                     {deleteLoading ? 'Deleting...' : 'Delete Build'}
    318                                 </Button>
    319                             </DialogActions>
    320                         </Dialog>
    321 
    322                     </Grid>
    323                 </Grid>
    324             </Grid>
     279                            </Box>
     280                        ))}
     281                    </Box>
     282                </DialogContent>
     283                <DialogActions>
     284                    <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button>
     285                </DialogActions>
     286            </Dialog>
     287
     288            <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="xl" fullWidth>
     289                <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
     290                    All Favorited Builds
     291                    <IconButton onClick={() => setOpenFavoritesDialog(false)}>
     292                        <CloseIcon/>
     293                    </IconButton>
     294                </DialogTitle>
     295                <DialogContent dividers>
     296                    <Box sx={{
     297                        display: 'grid',
     298                        gridTemplateColumns: {
     299                            xs: '1fr',
     300                            sm: 'repeat(2, 1fr)',
     301                            md: 'repeat(3, 1fr)',
     302                            lg: 'repeat(4, 1fr)',
     303                            xl: 'repeat(5, 1fr)'
     304                        },
     305                        gap: 2,
     306                        mt: 1
     307                    }}>
     308                        {data.favoriteBuilds.map((build: any) => (
     309                            <BuildCard
     310                                key={build.id}
     311                                build={build}
     312                                onClick={() => {
     313                                    setOpenFavoritesDialog(false);
     314                                    setSelectedBuildId(build.id);
     315                                }}
     316                            />
     317                        ))}
     318                    </Box>
     319                </DialogContent>
     320                <DialogActions>
     321                    <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button>
     322                </DialogActions>
     323            </Dialog>
     324
     325            <Dialog open={deleteDialog.open} onClose={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}>
     326                <DialogTitle>Delete Build</DialogTitle>
     327                <DialogContent>
     328                    <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography>
     329                    <Typography color="text.secondary">
     330                        Are you sure you want to permanently delete this build? This action cannot be undone.
     331                    </Typography>
     332                </DialogContent>
     333                <DialogActions>
     334                    <Button
     335                        onClick={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}
     336                        disabled={deleteLoading}
     337                    >
     338                        Cancel
     339                    </Button>
     340                    <Button
     341                        onClick={handleDelete}
     342                        variant="contained"
     343                        color="error"
     344                        disabled={deleteLoading}
     345                        startIcon={deleteLoading ? <CircularProgress size={20} /> : <DeleteIcon />}
     346                    >
     347                        {deleteLoading ? 'Deleting...' : 'Delete Build'}
     348                    </Button>
     349                </DialogActions>
     350            </Dialog>
    325351
    326352            <BuildDetailsDialog
     
    332358                    loadData();
    333359                }}
    334                 onClone={handleCloneWrapper}
    335360                isDashboardView={true}
    336361            />
Note: See TracChangeset for help on using the changeset viewer.