source: pages/index/+Page.tsx@ ae5d054

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

Added frontend elements

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