source: pages/index/+Page.tsx@ 8a7f936

main
Last change on this file since 8a7f936 was 8a7f936, checked in by Mihail <mihail2.naumov@…>, 6 months ago

Added Forge Page, added suggest component, fixed styling

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