Changeset e599341 for pages


Ignore:
Timestamp:
12/28/25 00:07:22 (7 months ago)
Author:
Mihail <mihail2.naumov@…>
Branches:
main
Children:
9c87509
Parents:
f7c0b0d
Message:

Added frontend elements

Location:
pages
Files:
3 edited

Legend:

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

    rf7c0b0d re599341  
    11import React, { useEffect, useState } from 'react';
    22import {
    3     Container, Grid, Box, Typography, TextField, MenuItem, Select,
    4     Slider, Button, Paper, InputAdornment
     3    Container, Box, Typography, TextField, MenuItem, Select,
     4    Slider, Button, Paper, InputAdornment, CircularProgress
    55} from '@mui/material';
    66import SearchIcon from '@mui/icons-material/Search';
     
    99import BuildCard from '../../components/BuildCard';
    1010import BuildDetailsDialog from '../../components/BuildDetailsDialog';
    11 
    1211import { onGetApprovedBuilds, onCloneBuild, onGetAuthState } from '../+Layout.telefunc';
    1312
     
    2726            const [userData, data] = await Promise.all([
    2827                onGetAuthState(),
    29                 onGetApprovedBuilds({ q: searchQuery })
     28                onGetApprovedBuilds({q: searchQuery})
    3029            ]);
    3130            setUserId(userData.userId);
     
    5857
    5958            setBuilds(sortedData);
     59        } catch (e) {
     60            console.error("Failed to load builds", e);
    6061        } finally {
    6162            setLoading(false);
     
    6566    useEffect(() => {
    6667        loadBuilds();
    67     }, [sortBy, priceRange, searchQuery]);
    68 
    69     useEffect(() => {
    70         loadBuilds();
    7168    }, [sortBy, searchQuery]);
    7269
     
    7471        if (!userId) return alert("Please login to clone builds!");
    7572        if (confirm(`Clone this build?`)) {
    76             await onCloneBuild({ buildId });
     73            await onCloneBuild({buildId});
    7774            alert("Build cloned!");
    7875            setSelectedBuildId(null);
     
    8178
    8279    return (
    83         <Container maxWidth="xl" sx={{ mt: 4, mb: 10 }}>
     80        <Container maxWidth={false} sx={{ mt: 4, mb: 10, px: { xs: 2, md: 4 } }}>
    8481            <Typography variant="h4" fontWeight="bold" gutterBottom>Completed Builds</Typography>
    8582            <Typography color="text.secondary" sx={{ mb: 4 }}>
     
    8784            </Typography>
    8885
    89             <Grid container spacing={4}>
    90                 <Grid item xs={12} md={3}>
     86            <Box sx={{ display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap: 4 }}>
     87
     88                <Box sx={{
     89                    width: { xs: '100%', md: '280px' },
     90                    flexShrink: 0
     91                }}>
    9192                    <Paper variant="outlined" sx={{ p: 3, position: 'sticky', top: 20 }}>
    9293                        <Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
     
    127128                        </Button>
    128129                    </Paper>
    129                 </Grid>
    130 
    131                 <Grid item xs={12} md={9}>
    132                     {/* Toolbar */}
     130                </Box>
     131
     132                <Box sx={{ flexGrow: 1 }}>
    133133                    <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
    134134                        <Typography fontWeight="bold">{builds.length} Builds Found</Typography>
     
    152152
    153153                    {loading ? (
    154                         <Box sx={{ p: 5, textAlign: 'center' }}>Loading...</Box>
     154                        <Box sx={{ p: 5, textAlign: 'center' }}>
     155                            <CircularProgress />
     156                        </Box>
    155157                    ) : (
    156                         <Grid container spacing={3}>
     158                        <Box
     159                            sx={{
     160                                display: 'grid',
     161                                gridTemplateColumns: {
     162                                    xs: '1fr',
     163                                    sm: 'repeat(2, 1fr)',
     164                                    md: 'repeat(3, 1fr)',
     165                                    lg: 'repeat(4, 1fr)',
     166                                    xl: 'repeat(5, 1fr)'
     167                                },
     168                                gap: 3,
     169                                width: '100%'
     170                            }}
     171                        >
    157172                            {builds.map((build) => (
    158                                 <Grid item xs={12} sm={6} lg={4} key={build.id} sx={{ display: 'flex' }}>
    159                                     <Box sx={{ width: '100%' }}>
    160                                         <BuildCard
    161                                             build={build}
    162                                             onClick={() => setSelectedBuildId(build.id)}
    163                                         />
    164                                     </Box>
    165                                 </Grid>
     173                                <BuildCard
     174                                    key={build.id}
     175                                    build={build}
     176                                    onClick={() => setSelectedBuildId(build.id)}
     177                                />
    166178                            ))}
    167179                            {builds.length === 0 && (
    168                                 <Grid item xs={12}>
    169                                     <Box sx={{ p: 5, textAlign: 'center', bgcolor: '#f5f5f5', borderRadius: 2 }}>
    170                                         <Typography>No builds found matching your filters.</Typography>
    171                                     </Box>
    172                                 </Grid>
     180                                <Box sx={{ gridColumn: '1 / -1', p: 5, textAlign: 'center', bgcolor: '#f5f5f5', borderRadius: 2 }}>
     181                                    <Typography>No builds found matching your filters.</Typography>
     182                                </Box>
    173183                            )}
    174                         </Grid>
     184                        </Box>
    175185                    )}
    176                 </Grid>
    177             </Grid>
    178 
     186                </Box>
     187            </Box>
     188
     189            {/* @ts-ignore */}
    179190            <BuildDetailsDialog
    180191                open={!!selectedBuildId}
     
    186197        </Container>
    187198    );
     199
    188200}
    189 
  • pages/dashboard/user/+Page.tsx

    rf7c0b0d re599341  
    99    Button,
    1010    CircularProgress,
    11     Card,
    12     CardContent,
    13     CardActionArea,
    14     IconButton
     11    IconButton,
     12    Grid,
     13    Dialog,
     14    DialogTitle,
     15    DialogContent,
     16    DialogActions
    1517} from '@mui/material';
    16 import Grid from '@mui/material/Grid';
    17 import {Dialog, DialogTitle, DialogContent, DialogActions} from '@mui/material';
    1818import CloseIcon from '@mui/icons-material/Close';
    1919
     
    2121import ComputerIcon from '@mui/icons-material/Computer';
    2222import FavoriteIcon from '@mui/icons-material/Favorite';
    23 import DeleteIcon from '@mui/icons-material/Delete';
    24 import EditIcon from '@mui/icons-material/Edit';
    2523
    2624import {getUserInfoAndData, onDeleteBuild} from "./userDashboard.telefunc";
     25import {onCloneBuild} from "../../+Layout.telefunc";
     26
     27import BuildCard from "../../../components/BuildCard";
     28import BuildDetailsDialog from "../../../components/BuildDetailsDialog";
    2729
    2830type DashboardData = {
     
    3638    const [loading, setLoading] = useState(true);
    3739    const [error, setError] = useState<string | null>(null);
     40
    3841    const [openMyBuildsDialog, setOpenMyBuildsDialog] = useState(false);
     42    const [openFavoritesDialog, setOpenFavoritesDialog] = useState(false);
     43
     44    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
    3945
    4046    const loadData = () => {
     
    6066            await onDeleteBuild({buildId});
    6167            loadData();
     68            setSelectedBuildId(null);
    6269        } catch (e) {
    6370            alert("Failed to delete build");
     
    6572    };
    6673
     74    const handleCloneWrapper = async (buildId: number) => {
     75        if (!data?.user) return alert("Please login to clone builds!");
     76        if (confirm(`Clone this build to your dashboard?`)) {
     77            await onCloneBuild({buildId});
     78            alert("Build cloned! Check your dashboard.");
     79            setSelectedBuildId(null);
     80            loadData();
     81        }
     82    };
     83
    6784    if (loading) return <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}><CircularProgress/></Box>;
    6885    if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error"
    6986                                                                                        variant="h6">{error}</Typography><Button
    7087        href="/auth/login" variant="contained">Login</Button></Container>;
    71 
    72     // @ts-ignore
     88    // console.log("Current User ID passed to dialog:", data?.user?.id);
     89
    7390    return (
    7491        <Container maxWidth="xl" sx={{mt: 4, mb: 4, color: 'white'}}>
    7592            <Grid container spacing={3}>
    76 
    7793                <Grid item xs={12} md={3}>
    7894                    <Paper elevation={3}
     
    8399                        <Typography variant="body2" color="text.secondary" gutterBottom>{data.user.email}</Typography>
    84100                        <Divider sx={{width: '100%', my: 2}}/>
    85                         {/*<Button variant="outlined" fullWidth color="primary" sx={{mb: 1}}>Edit Profile</Button>*/}
    86101                    </Paper>
    87102                </Grid>
     
    92107                        <Grid item xs={12}>
    93108                            <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
    94                                 <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
    95                                     <FavoriteIcon color="error" sx={{mr: 1}}/>
    96                                     <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography>
     109                                <Box sx={{
     110                                    display: 'flex',
     111                                    alignItems: 'center',
     112                                    justifyContent: 'space-between',
     113                                    mb: 2
     114                                }}>
     115                                    <Box sx={{display: 'flex', alignItems: 'center'}}>
     116                                        <FavoriteIcon color="error" sx={{mr: 1}}/>
     117                                        <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography>
     118                                    </Box>
     119
     120                                    {data.favoriteBuilds.length > 4 && (
     121                                        <Button
     122                                            variant="outlined"
     123                                            size="small"
     124                                            onClick={() => setOpenFavoritesDialog(true)}
     125                                        >
     126                                            See All ({data.favoriteBuilds.length})
     127                                        </Button>
     128                                    )}
    97129                                </Box>
    98130                                <Divider sx={{mb: 2}}/>
     
    103135                                ) : (
    104136                                    <Grid container spacing={2}>
    105                                         {data.favoriteBuilds.map((build: any) => (
     137                                        {data.favoriteBuilds.slice(0, 4).map((build: any) => (
    106138                                            <Grid item xs={12} sm={6} md={4} key={build.id}>
    107                                                 <BuildCard build={build}/>
     139                                                <BuildCard
     140                                                    build={build}
     141                                                    onClick={() => setSelectedBuildId(build.id)}
     142                                                />
    108143                                            </Grid>
    109144                                        ))}
     
    148183                                ) : (
    149184                                    <Grid container spacing={2}>
    150                                         {data.userBuilds.slice(0, 3).map((build: any) => (
    151                                             <Grid item xs={12} sm={6} md={3} key={build.id}>
     185                                        {data.userBuilds.slice(0, 4).map((build: any) => (
     186                                            <Grid item xs={12} sm={6} md={4} key={build.id}>
    152187                                                <BuildCard
    153188                                                    build={build}
    154                                                     onDelete={() => handleDelete(build.id)}
    155                                                     isOwner={true}
     189                                                    onClick={() => setSelectedBuildId(build.id)}
    156190                                                />
    157191                                            </Grid>
     
    162196                        </Grid>
    163197
    164                         <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="md"
     198                        <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="lg"
    165199                                fullWidth>
    166                             <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>All
    167                                 My Builds
     200                            <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
     201                                All My Builds
    168202                                <IconButton onClick={() => setOpenMyBuildsDialog(false)}>
    169203                                    <CloseIcon/>
     
    176210                                            <BuildCard
    177211                                                build={build}
    178                                                 onDelete={() => handleDelete(build.id)}
    179                                                 isOwner={true}
     212                                                onClick={() => {
     213                                                    setOpenMyBuildsDialog(false);
     214                                                    setSelectedBuildId(build.id);
     215                                                }}
    180216                                            />
    181217                                        </Grid>
     
    183219                                </Grid>
    184220                            </DialogContent>
    185 
    186221                            <DialogActions>
    187222                                <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button>
     
    189224                        </Dialog>
    190225
     226                        <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="lg"
     227                                fullWidth>
     228                            <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
     229                                All Favorited Builds
     230                                <IconButton onClick={() => setOpenFavoritesDialog(false)}>
     231                                    <CloseIcon/>
     232                                </IconButton>
     233                            </DialogTitle>
     234                            <DialogContent dividers>
     235                                <Grid container spacing={2} sx={{mt: 1}}>
     236                                    {data.favoriteBuilds.map((build: any) => (
     237                                        <Grid item xs={12} sm={6} md={4} key={build.id}>
     238                                            <BuildCard
     239                                                build={build}
     240                                                onClick={() => {
     241                                                    setOpenFavoritesDialog(false);
     242                                                    setSelectedBuildId(build.id);
     243                                                }}
     244                                            />
     245                                        </Grid>
     246                                    ))}
     247                                </Grid>
     248                            </DialogContent>
     249                            <DialogActions>
     250                                <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button>
     251                            </DialogActions>
     252                        </Dialog>
     253
    191254                    </Grid>
    192255                </Grid>
    193256            </Grid>
     257
     258            <BuildDetailsDialog
     259                open={!!selectedBuildId}
     260                buildId={selectedBuildId}
     261                currentUser={data?.user?.id ? Number(data.user.id) : undefined}
     262                onClose={() => {
     263                    setSelectedBuildId(null);
     264                    loadData();
     265                }}
     266                onClone={handleCloneWrapper}
     267            />
    194268        </Container>
    195269    );
    196270}
    197 
    198 function BuildCard({build, onDelete, isOwner}: { build: any, onDelete?: () => void, isOwner?: boolean }) {
    199     return (
    200         <Card sx={{height: '100%', display: 'flex', flexDirection: 'column'}}>
    201             <CardActionArea href={`/build/${build.id}`} sx={{flexGrow: 1}}>
    202                 <CardContent>
    203                     <Typography variant="subtitle1" fontWeight="bold" noWrap>
    204                         {build.name || `Build #${build.id}`}
    205                     </Typography>
    206                     <Typography variant="body2" color="text.secondary">
    207                         Created: {build.createdAt ? new Date(build.createdAt).toLocaleDateString() : 'Unknown'}
    208                     </Typography>
    209                 </CardContent>
    210             </CardActionArea>
    211 
    212             {isOwner && (
    213                 <Box sx={{display: 'flex', justifyContent: 'flex-end', p: 1, borderTop: '1px solid #eee'}}>
    214                     <IconButton size="small" href={`/build/edit/${build.id}`} color="primary">
    215                         <EditIcon fontSize="small"/>
    216                     </IconButton>
    217                     <IconButton size="small" onClick={onDelete} color="error">
    218                         <DeleteIcon fontSize="small"/>
    219                     </IconButton>
    220                 </Box>
    221             )}
    222         </Card>
    223     );
    224 }
  • pages/index/+Page.tsx

    rf7c0b0d re599341  
    1414export default function HomePage() {
    1515    const [data, setData] = useState<any>(null);
     16    const [allRanked, setAllRanked] = useState<any[]>([]);
    1617
    1718    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
    18 
    1919    const [openRankedPopup, setOpenRankedPopup] = useState(false);
    2020
     
    2323            try {
    2424                const [
    25                     authData, highestRankedBuilds, communityBuilds
     25                    authData,
     26                    highestRankedBuilds,
     27                    communityBuilds,
     28                    fullRankedList
    2629                ] = await Promise.all([
    2730                    onGetAuthState(),
    28                     onGetApprovedBuilds({ limit: 3 , sort: 'rating_desc' }),
    29                     onGetApprovedBuilds({ limit: 12 })
     31                    onGetApprovedBuilds({ limit: 5 , sort: 'rating_desc' }),
     32                    onGetApprovedBuilds({ limit: 12 }),
     33                    onGetApprovedBuilds({ limit: 10, sort: 'rating_desc' })
    3034                ]);
    3135
     
    3640                    communityBuilds: communityBuilds
    3741                });
     42                setAllRanked(fullRankedList);
    3843            } catch (error) {
    3944                console.error("Error loading homepage data:", error);
     
    6974                        Build, share, discuss, and discover custom PC configurations.
    7075                    </Typography>
    71                     <Button variant="contained" size="large" href="/forger" startIcon={<AutoFixHighIcon />}
     76                    <Button variant="contained" size="large" href="/forge" startIcon={<AutoFixHighIcon />}
    7277                            sx={{ fontSize: '1.2rem', px: 4, py: 1.5, mt: 2 }}>
    7378                        Start Forging
     
    9297                </Box>
    9398
    94                 <Grid container spacing={2} sx={{ mb: 8, alignItems: 'stretch' }}>
    95                     {/*<Grid item xs={12} md={3} sx={{ display: 'flex' }}>*/}
    96                     {/*    <Box sx={{*/}
    97                     {/*        width: '100%', p: 3, bgcolor: '#ff8201', color: 'black', borderRadius: 2,*/}
    98                     {/*        display: 'flex', flexDirection: 'column', justifyContent: 'center'*/}
    99                     {/*    }}>*/}
    100                     {/*        <Typography color={'black'} variant="h5" fontWeight="bold" gutterBottom>The Elite</Typography>*/}
    101                     {/*        <Typography variant="body1" fontWeight="bold">The top 3 community-voted builds.</Typography>*/}
    102                     {/*    </Box>*/}
    103                     {/*</Grid>*/}
    104 
     99                <Grid container spacing={3} sx={{ mb: 8, alignItems: 'stretch' }}>
    105100                    {data.prebuilts.slice(0, 3).map((build: any) => (
    106101                        <Grid item xs={12} sm={6} md={3} key={build.id} sx={{ display: 'flex' }}>
     
    114109                    ))}
    115110                </Grid>
    116 
    117111
    118112                <SectionHeader title="Community Forge" subtitle="Fresh builds from users around the world."/>
     
    133127            </Container>
    134128
    135 
    136129            <BuildDetailsDialog
    137130                open={!!selectedBuildId}
     
    142135            />
    143136
    144 
    145             <Dialog open={openRankedPopup} onClose={() => setOpenRankedPopup(false)} maxWidth="lg" fullWidth>
     137            <Dialog open={openRankedPopup} onClose={() => setOpenRankedPopup(false)} maxWidth="lg" fullWidth scroll="paper">
    146138                <DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
    147                     Hall of Fame (All Top Ranked)
     139                    Hall of Fame (Top Rated)
    148140                    <IconButton onClick={() => setOpenRankedPopup(false)}><CloseIcon /></IconButton>
    149141                </DialogTitle>
    150142                <DialogContent dividers>
    151143                    <Grid container spacing={3}>
    152                         {data.prebuilts.concat(data.communityBuilds).map((build: any) => (
    153                             <Grid item xs={12} sm={6} md={3} key={`popup-${build.id}`}>
    154                                 <BuildCard
    155                                     build={build}
    156                                     onClick={() => {
    157                                         setOpenRankedPopup(false);
    158                                         setSelectedBuildId(build.id); // Open details from popup
    159                                     }}
    160                                 />
     144                        {allRanked.map((build: any, index: number) => (
     145                            <Grid item xs={12} sm={6} md={3} key={`ranked-${build.id}`}>
     146                                <Box sx={{ position: 'relative' }}>
     147                                    <Box sx={{
     148                                        position: 'absolute', top: -10, left: -10, zIndex: 1,
     149                                        width: 30, height: 30, borderRadius: '50%',
     150                                        bgcolor: index < 3 ? '#ff8201' : 'grey.700', color: 'white',
     151                                        display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 'bold'
     152                                    }}>
     153                                        #{index + 1}
     154                                    </Box>
     155                                    <BuildCard
     156                                        build={build}
     157                                        onClick={() => {
     158                                            setOpenRankedPopup(false);
     159                                            setSelectedBuildId(build.id);
     160                                        }}
     161                                    />
     162                                </Box>
    161163                            </Grid>
    162164                        ))}
     
    171173function SectionHeader({ title, subtitle }: { title: string, subtitle: string }) {
    172174    return (
    173         <Box sx={{ mb: 4, borderLeft: '5px solid #1976d2', pl: 2 }}>
     175        <Box sx={{ mb: 4, borderLeft: '5px solid #ff8201', pl: 2 }}>
    174176            <Typography variant="h4" fontWeight="bold" color="text.primary">{title}</Typography>
    175177            <Typography variant="subtitle1" color="text.secondary">{subtitle}</Typography>
Note: See TracChangeset for help on using the changeset viewer.