Changeset 546a194 for pages/dashboard/user/+Page.tsx
- Timestamp:
- 02/10/26 14:20:22 (5 months ago)
- Branches:
- main
- Children:
- 3a9c59c, 92fafb3
- Parents:
- f727252
- File:
-
- 1 edited
-
pages/dashboard/user/+Page.tsx (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pages/dashboard/user/+Page.tsx
rf727252 r546a194 10 10 CircularProgress, 11 11 IconButton, 12 Grid,13 12 Dialog, 14 13 DialogTitle, … … 24 23 25 24 import {getUserInfoAndData, onDeleteBuild} from "./userDashboard.telefunc"; 26 import {onCloneBuild} from "../../+Layout.telefunc";27 25 28 26 import BuildCard from "../../../components/BuildCard"; … … 72 70 await onDeleteBuild({buildId: deleteDialog.buildId}); 73 71 setDeleteDialog({ open: false, buildId: null, buildName: '' }); 74 loadData(); // refresh na user i favorite builds72 loadData(); 75 73 setSelectedBuildId(null); 76 74 } catch (e) { … … 81 79 }; 82 80 83 const handleCloneWrapper = async (buildId: number) => {84 if (!data?.user) return alert("Please login to clone builds!");85 if (confirm(`Clone this build to your dashboard?`)) {86 await onCloneBuild({buildId});87 alert("Build cloned! Check your dashboard.");88 setSelectedBuildId(null);89 loadData();90 }91 };92 93 81 if (loading) return <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}><CircularProgress/></Box>; 94 if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error" 95 variant="h6">{error}</Typography><Button 96 href="/auth/login" variant="contained">Login</Button></Container>; 82 if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error" variant="h6">{error}</Typography><Button href="/auth/login" variant="contained">Login</Button></Container>; 97 83 98 84 return ( 99 <Container maxWidth="xl" sx={{mt: 4, mb: 4, color: 'white'}}> 100 <Grid container spacing={3}> 101 <Grid item xs={12} md={3}> 102 <Paper elevation={3} 103 sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}> 104 <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}><PersonIcon 105 sx={{fontSize: 60}}/></Avatar> 85 <Container maxWidth="xl" sx={{mb: 4, color: 'white'}}> 86 <Box sx={{ 87 display: 'grid', 88 gridTemplateColumns: { 89 xs: '1fr', 90 md: '280px 1fr' 91 }, 92 gap: 2 93 }}> 94 <Box> 95 <Paper elevation={3} sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}> 96 <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}> 97 <PersonIcon sx={{fontSize: 60}}/> 98 </Avatar> 106 99 <Typography variant="h5" fontWeight="bold" gutterBottom>{data.user.username}</Typography> 107 100 <Typography variant="body2" color="text.secondary" gutterBottom>{data.user.email}</Typography> 108 101 <Divider sx={{width: '100%', my: 2}}/> 109 102 </Paper> 110 </Grid> 111 112 <Grid item xs={12} md={9}> 113 <Grid container spacing={3} direction="column"> 114 115 <Grid item xs={12}> 116 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}> 117 <Box sx={{ 118 display: 'flex', 119 alignItems: 'center', 120 justifyContent: 'space-between', 121 mb: 2 122 }}> 123 <Box sx={{display: 'flex', alignItems: 'center'}}> 124 <FavoriteIcon color="error" sx={{mr: 1}}/> 125 <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography> 126 </Box> 127 128 {data.favoriteBuilds.length > 4 && ( 103 </Box> 104 105 <Box sx={{ 106 display: 'flex', 107 flexDirection: 'column', 108 gap: 3 109 }}> 110 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}> 111 <Box sx={{ 112 display: 'flex', 113 alignItems: 'center', 114 justifyContent: 'space-between', 115 mb: 2 116 }}> 117 <Box sx={{display: 'flex', alignItems: 'center'}}> 118 <FavoriteIcon color="error" sx={{mr: 1}}/> 119 <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography> 120 </Box> 121 122 {data.favoriteBuilds.length > 6 && ( 123 <Button 124 variant="outlined" 125 size="small" 126 onClick={() => setOpenFavoritesDialog(true)} 127 > 128 See All ({data.favoriteBuilds.length}) 129 </Button> 130 )} 131 </Box> 132 <Divider sx={{mb: 2}}/> 133 134 {data.favoriteBuilds.length === 0 ? ( 135 <Typography color="text.secondary" align="center" sx={{mt: 4}}> 136 You haven't favorited any builds yet. 137 </Typography> 138 ) : ( 139 <Box sx={{ 140 display: 'grid', 141 gridTemplateColumns: { 142 xs: '1fr', 143 sm: 'repeat(2, 1fr)', 144 md: 'repeat(3, 1fr)', 145 lg: 'repeat(4, 1fr)', 146 xl: 'repeat(6, 1fr)' 147 }, 148 gap: 2 149 }}> 150 {data.favoriteBuilds.slice(0, 6).map((build: any) => ( 151 <BuildCard 152 key={build.id} 153 build={build} 154 onClick={() => setSelectedBuildId(build.id)} 155 /> 156 ))} 157 </Box> 158 )} 159 </Paper> 160 161 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}> 162 <Box sx={{ 163 display: 'flex', 164 alignItems: 'center', 165 justifyContent: 'space-between', 166 mb: 2 167 }}> 168 <Box sx={{display: 'flex', alignItems: 'center'}}> 169 <ComputerIcon color="primary" sx={{mr: 1}}/> 170 <Typography variant="h6" fontWeight="bold">My Builds</Typography> 171 </Box> 172 173 {data.userBuilds.length > 6 && ( 174 <Button 175 variant="outlined" 176 size="small" 177 onClick={() => setOpenMyBuildsDialog(true)} 178 > 179 See All ({data.userBuilds.length}) 180 </Button> 181 )} 182 </Box> 183 <Divider sx={{mb: 2}}/> 184 185 {data.userBuilds.length === 0 ? ( 186 <Box sx={{textAlign: 'center', mt: 4}}> 187 <Typography color="text.secondary" gutterBottom> 188 You haven't created any builds yet. 189 </Typography> 190 <Button variant="contained" href="/forge" sx={{color: 'white', fontWeight: 'bolder'}}> 191 Start Forging 192 </Button> 193 </Box> 194 ) : ( 195 <Box sx={{ 196 display: 'grid', 197 gridTemplateColumns: { 198 xs: '1fr', 199 sm: 'repeat(2, 1fr)', 200 md: 'repeat(3, 1fr)', 201 lg: 'repeat(4, 1fr)', 202 xl: 'repeat(6, 1fr)' 203 }, 204 gap: 2 205 }}> 206 {data.userBuilds.slice(0, 6).map((build: any) => ( 207 <Box key={build.id} sx={{ display: 'flex', flexDirection: 'column' }}> 208 <Box sx={{ flexGrow: 1 }}> 209 <BuildCard 210 build={build} 211 onClick={() => setSelectedBuildId(build.id)} 212 /> 213 </Box> 129 214 <Button 130 215 variant="outlined" 216 color="error" 131 217 size="small" 132 onClick={() => setOpenFavoritesDialog(true)} 218 startIcon={<DeleteIcon/>} 219 onClick={(e) => { 220 e.stopPropagation(); 221 openDeleteDialog(build.id, build.name); 222 }} 223 sx={{ mt: 1, width: '100%' }} 133 224 > 134 See All ({data.favoriteBuilds.length})225 Delete 135 226 </Button> 136 )} 227 </Box> 228 ))} 229 </Box> 230 )} 231 </Paper> 232 </Box> 233 </Box> 234 235 <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="xl" fullWidth> 236 <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}> 237 All My Builds 238 <IconButton onClick={() => setOpenMyBuildsDialog(false)}> 239 <CloseIcon/> 240 </IconButton> 241 </DialogTitle> 242 <DialogContent dividers> 243 <Box sx={{ 244 display: 'grid', 245 gridTemplateColumns: { 246 xs: '1fr', 247 sm: 'repeat(2, 1fr)', 248 md: 'repeat(3, 1fr)', 249 lg: 'repeat(4, 1fr)', 250 xl: 'repeat(5, 1fr)' 251 }, 252 gap: 2, 253 mt: 1 254 }}> 255 {data.userBuilds.map((build: any) => ( 256 <Box key={build.id}> 257 <BuildCard 258 build={build} 259 onClick={() => { 260 setOpenMyBuildsDialog(false); 261 setSelectedBuildId(build.id); 262 }} 263 /> 264 <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}> 265 <Button 266 variant="outlined" 267 color="error" 268 size="small" 269 startIcon={<DeleteIcon/>} 270 onClick={(e) => { 271 e.stopPropagation(); 272 openDeleteDialog(build.id, build.name); 273 }} 274 sx={{width: '100%'}} 275 > 276 Delete 277 </Button> 137 278 </Box> 138 <Divider sx={{mb: 2}}/> 139 140 {data.favoriteBuilds.length === 0 ? ( 141 <Typography color="text.secondary" align="center" sx={{mt: 4}}>You haven't favorited 142 any builds yet.</Typography> 143 ) : ( 144 <Grid container spacing={2}> 145 {data.favoriteBuilds.slice(0, 4).map((build: any) => ( 146 <Grid item xs={12} sm={6} md={4} key={build.id}> 147 <BuildCard 148 build={build} 149 onClick={() => setSelectedBuildId(build.id)} 150 /> 151 </Grid> 152 ))} 153 </Grid> 154 )} 155 </Paper> 156 </Grid> 157 158 <Grid item xs={12}> 159 <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}> 160 <Box sx={{ 161 display: 'flex', 162 alignItems: 'center', 163 justifyContent: 'space-between', 164 mb: 2 165 }}> 166 <Box sx={{display: 'flex', alignItems: 'center'}}> 167 <ComputerIcon color="primary" sx={{mr: 1}}/> 168 <Typography variant="h6" fontWeight="bold">My Builds</Typography> 169 </Box> 170 171 {data.userBuilds.length > 4 && ( 172 <Button 173 variant="outlined" 174 size="small" 175 onClick={() => setOpenMyBuildsDialog(true)} 176 > 177 See All ({data.userBuilds.length}) 178 </Button> 179 )} 180 </Box> 181 <Divider sx={{mb: 2}}/> 182 183 {data.userBuilds.length === 0 ? ( 184 <Box sx={{textAlign: 'center', mt: 4}}> 185 <Typography color="text.secondary" gutterBottom>You haven't created any builds 186 yet.</Typography> 187 <Button variant="contained" href="/forge" 188 sx={{color: 'white', fontWeight: 'bolder'}}>Start Forging</Button> 189 </Box> 190 ) : ( 191 <Grid container spacing={2}> 192 {data.userBuilds.slice(0, 4).map((build: any) => ( 193 <Grid item xs={12} sm={6} md={4} key={build.id}> 194 <Box sx={{ position: 'relative' }}> 195 <BuildCard 196 build={build} 197 onClick={() => setSelectedBuildId(build.id)} 198 /> 199 <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}> 200 <Button 201 variant="outlined" 202 color="error" 203 size="small" 204 startIcon={<DeleteIcon />} 205 onClick={(e) => { 206 e.stopPropagation(); 207 openDeleteDialog(build.id, build.name); 208 }} 209 sx={{ width: '100%' }} 210 > 211 Delete 212 </Button> 213 </Box> 214 </Box> 215 </Grid> 216 ))} 217 </Grid> 218 )} 219 </Paper> 220 </Grid> 221 222 <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="lg" 223 fullWidth> 224 <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}> 225 All My Builds 226 <IconButton onClick={() => setOpenMyBuildsDialog(false)}> 227 <CloseIcon/> 228 </IconButton> 229 </DialogTitle> 230 <DialogContent dividers> 231 <Grid container spacing={2} sx={{mt: 1}}> 232 {data.userBuilds.map((build: any) => ( 233 <Grid item xs={12} sm={6} md={4} key={build.id}> 234 <Box sx={{ position: 'relative' }}> 235 <BuildCard 236 build={build} 237 onClick={() => { 238 setOpenMyBuildsDialog(false); 239 setSelectedBuildId(build.id); 240 }} 241 /> 242 <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}> 243 <Button 244 variant="outlined" 245 color="error" 246 size="small" 247 startIcon={<DeleteIcon />} 248 onClick={(e) => { 249 e.stopPropagation(); 250 openDeleteDialog(build.id, build.name); 251 }} 252 sx={{ width: '100%' }} 253 > 254 Delete 255 </Button> 256 </Box> 257 </Box> 258 </Grid> 259 ))} 260 </Grid> 261 </DialogContent> 262 <DialogActions> 263 <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button> 264 </DialogActions> 265 </Dialog> 266 267 <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="lg" 268 fullWidth> 269 <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}> 270 All Favorited Builds 271 <IconButton onClick={() => setOpenFavoritesDialog(false)}> 272 <CloseIcon/> 273 </IconButton> 274 </DialogTitle> 275 <DialogContent dividers> 276 <Grid container spacing={2} sx={{mt: 1}}> 277 {data.favoriteBuilds.map((build: any) => ( 278 <Grid item xs={12} sm={6} md={4} key={build.id}> 279 <BuildCard 280 build={build} 281 onClick={() => { 282 setOpenFavoritesDialog(false); 283 setSelectedBuildId(build.id); 284 }} 285 /> 286 </Grid> 287 ))} 288 </Grid> 289 </DialogContent> 290 <DialogActions> 291 <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button> 292 </DialogActions> 293 </Dialog> 294 295 <Dialog open={deleteDialog.open} onClose={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}> 296 <DialogTitle>Delete Build</DialogTitle> 297 <DialogContent> 298 <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography> 299 <Typography color="text.secondary"> 300 Are you sure you want to permanently delete this build? This action cannot be undone. 301 </Typography> 302 </DialogContent> 303 <DialogActions> 304 <Button 305 onClick={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })} 306 disabled={deleteLoading} 307 > 308 Cancel 309 </Button> 310 <Button 311 onClick={handleDelete} 312 variant="contained" 313 color="error" 314 disabled={deleteLoading} 315 startIcon={deleteLoading ? <CircularProgress size={20} /> : <DeleteIcon />} 316 > 317 {deleteLoading ? 'Deleting...' : 'Delete Build'} 318 </Button> 319 </DialogActions> 320 </Dialog> 321 322 </Grid> 323 </Grid> 324 </Grid> 279 </Box> 280 ))} 281 </Box> 282 </DialogContent> 283 <DialogActions> 284 <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button> 285 </DialogActions> 286 </Dialog> 287 288 <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="xl" fullWidth> 289 <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}> 290 All Favorited Builds 291 <IconButton onClick={() => setOpenFavoritesDialog(false)}> 292 <CloseIcon/> 293 </IconButton> 294 </DialogTitle> 295 <DialogContent dividers> 296 <Box sx={{ 297 display: 'grid', 298 gridTemplateColumns: { 299 xs: '1fr', 300 sm: 'repeat(2, 1fr)', 301 md: 'repeat(3, 1fr)', 302 lg: 'repeat(4, 1fr)', 303 xl: 'repeat(5, 1fr)' 304 }, 305 gap: 2, 306 mt: 1 307 }}> 308 {data.favoriteBuilds.map((build: any) => ( 309 <BuildCard 310 key={build.id} 311 build={build} 312 onClick={() => { 313 setOpenFavoritesDialog(false); 314 setSelectedBuildId(build.id); 315 }} 316 /> 317 ))} 318 </Box> 319 </DialogContent> 320 <DialogActions> 321 <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button> 322 </DialogActions> 323 </Dialog> 324 325 <Dialog open={deleteDialog.open} onClose={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}> 326 <DialogTitle>Delete Build</DialogTitle> 327 <DialogContent> 328 <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography> 329 <Typography color="text.secondary"> 330 Are you sure you want to permanently delete this build? This action cannot be undone. 331 </Typography> 332 </DialogContent> 333 <DialogActions> 334 <Button 335 onClick={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })} 336 disabled={deleteLoading} 337 > 338 Cancel 339 </Button> 340 <Button 341 onClick={handleDelete} 342 variant="contained" 343 color="error" 344 disabled={deleteLoading} 345 startIcon={deleteLoading ? <CircularProgress size={20} /> : <DeleteIcon />} 346 > 347 {deleteLoading ? 'Deleting...' : 'Delete Build'} 348 </Button> 349 </DialogActions> 350 </Dialog> 325 351 326 352 <BuildDetailsDialog … … 332 358 loadData(); 333 359 }} 334 onClone={handleCloneWrapper}335 360 isDashboardView={true} 336 361 />
Note:
See TracChangeset
for help on using the changeset viewer.
