source: pages/dashboard/user/+Page.tsx@ dda6f51

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

Added frontend elements

  • Property mode set to 100644
File size: 12.8 KB
RevLine 
[40ac7a9]1import React, {useEffect, useState} from 'react';
2import {
3 Container,
4 Paper,
5 Typography,
6 Box,
7 Avatar,
8 Divider,
9 Button,
10 CircularProgress,
[e599341]11 IconButton,
12 Grid,
13 Dialog,
14 DialogTitle,
15 DialogContent,
16 DialogActions
[40ac7a9]17} from '@mui/material';
18import CloseIcon from '@mui/icons-material/Close';
19
20import PersonIcon from '@mui/icons-material/Person';
21import ComputerIcon from '@mui/icons-material/Computer';
22import FavoriteIcon from '@mui/icons-material/Favorite';
23
24import {getUserInfoAndData, onDeleteBuild} from "./userDashboard.telefunc";
[e599341]25import {onCloneBuild} from "../../+Layout.telefunc";
26
27import BuildCard from "../../../components/BuildCard";
28import BuildDetailsDialog from "../../../components/BuildDetailsDialog";
[40ac7a9]29
30type DashboardData = {
31 user: { username: string; email?: string; [key: string]: any };
32 userBuilds: any[];
33 favoriteBuilds: any[];
34};
35
36export default function UserDashboard() {
37 const [data, setData] = useState<DashboardData | null>(null);
38 const [loading, setLoading] = useState(true);
39 const [error, setError] = useState<string | null>(null);
[e599341]40
[40ac7a9]41 const [openMyBuildsDialog, setOpenMyBuildsDialog] = useState(false);
[e599341]42 const [openFavoritesDialog, setOpenFavoritesDialog] = useState(false);
43
44 const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
[40ac7a9]45
46 const loadData = () => {
47 getUserInfoAndData()
48 .then((result) => {
49 setData(result);
50 setLoading(false);
51 })
52 .catch((err) => {
53 console.error(err);
54 setError("Failed to load dashboard. Please log in.");
55 setLoading(false);
56 });
57 };
58
59 useEffect(() => {
60 loadData();
61 }, []);
62
63 const handleDelete = async (buildId: number) => {
64 if (!confirm("Are you sure you want to delete this build?")) return;
65 try {
66 await onDeleteBuild({buildId});
67 loadData();
[e599341]68 setSelectedBuildId(null);
[40ac7a9]69 } catch (e) {
70 alert("Failed to delete build");
71 }
72 };
73
[e599341]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
[40ac7a9]84 if (loading) return <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}><CircularProgress/></Box>;
85 if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error"
86 variant="h6">{error}</Typography><Button
87 href="/auth/login" variant="contained">Login</Button></Container>;
[e599341]88 // console.log("Current User ID passed to dialog:", data?.user?.id);
[40ac7a9]89
90 return (
91 <Container maxWidth="xl" sx={{mt: 4, mb: 4, color: 'white'}}>
92 <Grid container spacing={3}>
93 <Grid item xs={12} md={3}>
94 <Paper elevation={3}
95 sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}>
96 <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}><PersonIcon
97 sx={{fontSize: 60}}/></Avatar>
98 <Typography variant="h5" fontWeight="bold" gutterBottom>{data.user.username}</Typography>
99 <Typography variant="body2" color="text.secondary" gutterBottom>{data.user.email}</Typography>
100 <Divider sx={{width: '100%', my: 2}}/>
101 </Paper>
102 </Grid>
103
104 <Grid item xs={12} md={9}>
105 <Grid container spacing={3} direction="column">
106
107 <Grid item xs={12}>
108 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
[e599341]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 )}
[40ac7a9]129 </Box>
130 <Divider sx={{mb: 2}}/>
131
132 {data.favoriteBuilds.length === 0 ? (
133 <Typography color="text.secondary" align="center" sx={{mt: 4}}>You haven't favorited
134 any builds yet.</Typography>
135 ) : (
136 <Grid container spacing={2}>
[e599341]137 {data.favoriteBuilds.slice(0, 4).map((build: any) => (
[40ac7a9]138 <Grid item xs={12} sm={6} md={4} key={build.id}>
[e599341]139 <BuildCard
140 build={build}
141 onClick={() => setSelectedBuildId(build.id)}
142 />
[40ac7a9]143 </Grid>
144 ))}
145 </Grid>
146 )}
147 </Paper>
148 </Grid>
149
150 <Grid item xs={12}>
151 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
152
153 <Box sx={{
154 display: 'flex',
155 alignItems: 'center',
156 justifyContent: 'space-between',
157 mb: 2
158 }}>
159 <Box sx={{display: 'flex', alignItems: 'center'}}>
160 <ComputerIcon color="primary" sx={{mr: 1}}/>
161 <Typography variant="h6" fontWeight="bold">My Builds</Typography>
162 </Box>
163
164 {data.userBuilds.length > 4 && (
165 <Button
166 variant="outlined"
167 size="small"
168 onClick={() => setOpenMyBuildsDialog(true)}
169 >
170 See All ({data.userBuilds.length})
171 </Button>
172 )}
173 </Box>
174 <Divider sx={{mb: 2}}/>
175
176 {data.userBuilds.length === 0 ? (
177 <Box sx={{textAlign: 'center', mt: 4}}>
178 <Typography color="text.secondary" gutterBottom>You haven't created any builds
179 yet.</Typography>
180 <Button variant="contained" href="/forge"
181 sx={{color: 'white', fontWeight: 'bolder'}}>Start Forging</Button>
182 </Box>
183 ) : (
184 <Grid container spacing={2}>
[e599341]185 {data.userBuilds.slice(0, 4).map((build: any) => (
186 <Grid item xs={12} sm={6} md={4} key={build.id}>
[40ac7a9]187 <BuildCard
188 build={build}
[e599341]189 onClick={() => setSelectedBuildId(build.id)}
[40ac7a9]190 />
191 </Grid>
192 ))}
193 </Grid>
194 )}
195 </Paper>
196 </Grid>
197
[e599341]198 <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="lg"
[40ac7a9]199 fullWidth>
[e599341]200 <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
201 All My Builds
[40ac7a9]202 <IconButton onClick={() => setOpenMyBuildsDialog(false)}>
203 <CloseIcon/>
204 </IconButton>
205 </DialogTitle>
206 <DialogContent dividers>
207 <Grid container spacing={2} sx={{mt: 1}}>
208 {data.userBuilds.map((build: any) => (
209 <Grid item xs={12} sm={6} md={4} key={build.id}>
210 <BuildCard
211 build={build}
[e599341]212 onClick={() => {
213 setOpenMyBuildsDialog(false);
214 setSelectedBuildId(build.id);
215 }}
[40ac7a9]216 />
217 </Grid>
218 ))}
219 </Grid>
220 </DialogContent>
221 <DialogActions>
222 <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button>
223 </DialogActions>
224 </Dialog>
225
[e599341]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
[40ac7a9]254 </Grid>
255 </Grid>
256 </Grid>
[e599341]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 />
[40ac7a9]268 </Container>
269 );
270}
Note: See TracBrowser for help on using the repository browser.