source: pages/index/+Page.tsx@ 1bf6e1f

main
Last change on this file since 1bf6e1f was 1bf6e1f, checked in by Mihail <mihail2.naumov@…>, 7 months ago

Implemented part of the frontend (index, user, completedBuilds).

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[40ac7a9]1import React, { useEffect, useState } from 'react';
2import {
[1bf6e1f]3 Container, Box, Typography, Button, Grid, IconButton, Dialog, DialogTitle, DialogContent
[40ac7a9]4} from '@mui/material';
5import CloseIcon from '@mui/icons-material/Close';
6import AutoFixHighIcon from '@mui/icons-material/AutoFixHigh';
[1bf6e1f]7import ListIcon from '@mui/icons-material/List';
[40ac7a9]8
[1bf6e1f]9import BuildDetailsDialog from '../../components/BuildDetailsDialog';
10import BuildCard from '../../components/BuildCard';
[40ac7a9]11
[1bf6e1f]12import { onGetApprovedBuilds, onGetAuthState, onCloneBuild } from '../+Layout.telefunc';
[40ac7a9]13
14export default function HomePage() {
15 const [data, setData] = useState<any>(null);
16
[1bf6e1f]17 const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
18
[40ac7a9]19 const [openRankedPopup, setOpenRankedPopup] = useState(false);
20
21 useEffect(() => {
[1bf6e1f]22 async function loadSite() {
23 try {
[40ac7a9]24 const [
[1bf6e1f]25 authData, highestRankedBuilds, communityBuilds
[40ac7a9]26 ] = await Promise.all([
[67dfe57]27 onGetAuthState(),
[1bf6e1f]28 onGetApprovedBuilds({ limit: 3 , sort: 'rating_desc' }),
[40ac7a9]29 onGetApprovedBuilds({ limit: 12 })
30 ]);
31
32 setData({
33 isLoggedIn: authData.isLoggedIn,
34 userId: authData.userId,
35 prebuilts: highestRankedBuilds,
[1bf6e1f]36 communityBuilds: communityBuilds
[40ac7a9]37 });
38 } catch (error) {
39 console.error("Error loading homepage data:", error);
40 }
[1bf6e1f]41 }
42 loadSite();
43 }, []);
[40ac7a9]44
[1bf6e1f]45 const handleCloneWrapper = async (buildId: number) => {
[40ac7a9]46 if (!data?.isLoggedIn) return alert("Please login to clone builds!");
[1bf6e1f]47 if (confirm(`Clone this build to your dashboard?`)) {
48 await onCloneBuild({ buildId });
[40ac7a9]49 alert("Build cloned! Check your dashboard.");
[1bf6e1f]50 setSelectedBuildId(null);
[40ac7a9]51 }
52 };
53
54 if (!data) return <Box sx={{ p: 10, textAlign: 'center' }}>Loading Forge...</Box>;
55
56 return (
57 <Box>
58 <Box sx={{
59 position: 'relative', height: '500px',
60 display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white',
[1bf6e1f]61 '&::before': {
62 content: '""', position: 'absolute', top: 0, left: 0, width: '100%', height: '100%',
63 backgroundColor: 'rgba(0,0,0,0.6)'
64 }
[40ac7a9]65 }}>
66 <Box sx={{ position: 'relative', textAlign: 'center', zIndex: 1, p: 2 }}>
67 <Typography variant="h2" fontWeight="bold" gutterBottom>Forge Your Ultimate Machine</Typography>
[1bf6e1f]68 <Typography variant="h5" sx={{ maxWidth: '800px', mx: 'auto', mb: 1 }}>
[40ac7a9]69 Build, share, discuss, and discover custom PC configurations.
70 </Typography>
[1bf6e1f]71 <Button variant="contained" size="large" href="/forger" startIcon={<AutoFixHighIcon />}
72 sx={{ fontSize: '1.2rem', px: 4, py: 1.5, mt: 2 }}>
[40ac7a9]73 Start Forging
74 </Button>
75 </Box>
76 </Box>
77
78 <Container maxWidth="xl" sx={{ mt: 6, mb: 10 }}>
[1bf6e1f]79 <Box sx={{
80 mb: 4, borderLeft: '5px solid #ff8201', pl: 2,
81 display: 'flex', justifyContent: 'space-between', alignItems: 'end'
82 }}>
[40ac7a9]83 <Box>
84 <Typography variant="h4" fontWeight="bold">Hall of Fame</Typography>
[1bf6e1f]85 <Typography variant="subtitle1" color="text.secondary">
86 The highest rated configurations from across the community.
87 </Typography>
[40ac7a9]88 </Box>
[1bf6e1f]89 <Button variant="outlined" startIcon={<ListIcon />} onClick={() => setOpenRankedPopup(true)}>
[40ac7a9]90 Show All Top Ranked
91 </Button>
92 </Box>
93
[1bf6e1f]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
105 {data.prebuilts.slice(0, 3).map((build: any) => (
106 <Grid item xs={12} sm={6} md={3} key={build.id} sx={{ display: 'flex' }}>
107 <Box sx={{ width: '100%' }}>
108 <BuildCard
109 build={build}
110 onClick={() => setSelectedBuildId(build.id)}
111 />
112 </Box>
[40ac7a9]113 </Grid>
114 ))}
115 </Grid>
116
[1bf6e1f]117
[40ac7a9]118 <SectionHeader title="Community Forge" subtitle="Fresh builds from users around the world."/>
119 <Grid container spacing={3}>
120 {data.communityBuilds.map((build: any) => (
121 <Grid item xs={12} sm={6} md={3} key={build.id}>
[1bf6e1f]122 <BuildCard
123 build={build}
124 onClick={() => setSelectedBuildId(build.id)}
125 />
[40ac7a9]126 </Grid>
127 ))}
128 </Grid>
129
130 <Box sx={{ display: 'flex', justifyContent: 'center', mt: 6 }}>
131 <Button variant="outlined" size="large" href="/completed-builds">View All Community Builds</Button>
132 </Box>
133 </Container>
134
[1bf6e1f]135
136 <BuildDetailsDialog
137 open={!!selectedBuildId}
138 buildId={selectedBuildId}
139 currentUser={data.userId}
140 onClose={() => setSelectedBuildId(null)}
141 onClone={handleCloneWrapper}
142 />
[40ac7a9]143
144
145 <Dialog open={openRankedPopup} onClose={() => setOpenRankedPopup(false)} maxWidth="lg" fullWidth>
146 <DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
147 Hall of Fame (All Top Ranked)
148 <IconButton onClick={() => setOpenRankedPopup(false)}><CloseIcon /></IconButton>
149 </DialogTitle>
150 <DialogContent dividers>
151 <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}`}>
[1bf6e1f]154 <BuildCard
155 build={build}
156 onClick={() => {
157 setOpenRankedPopup(false);
158 setSelectedBuildId(build.id); // Open details from popup
159 }}
160 />
[40ac7a9]161 </Grid>
162 ))}
163 </Grid>
164 </DialogContent>
165 </Dialog>
166
167 </Box>
168 );
169}
170
171function SectionHeader({ title, subtitle }: { title: string, subtitle: string }) {
172 return (
173 <Box sx={{ mb: 4, borderLeft: '5px solid #1976d2', pl: 2 }}>
174 <Typography variant="h4" fontWeight="bold" color="text.primary">{title}</Typography>
175 <Typography variant="subtitle1" color="text.secondary">{subtitle}</Typography>
176 </Box>
177 );
178}
Note: See TracBrowser for help on using the repository browser.