diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 39f442f..e71ef1f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -24,7 +24,8 @@ import { Autocomplete, CircularProgress, ListItemAvatar, - ListSubheader + ListSubheader, + alpha } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; import SearchIcon from '@mui/icons-material/Search'; @@ -338,12 +339,18 @@ const App: React.FC = () => { - + bgcolor: (theme) => alpha(theme.palette.background.paper, 0.8), + backdropFilter: 'blur(12px)', + color: 'text.primary', + zIndex: (theme) => theme.zIndex.drawer + 1 + }} + > diff --git a/frontend/src/pages/flavors/FlavorDetail.tsx b/frontend/src/pages/flavors/FlavorDetail.tsx index 914a188..dca26f5 100644 --- a/frontend/src/pages/flavors/FlavorDetail.tsx +++ b/frontend/src/pages/flavors/FlavorDetail.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { useParams, Link } from 'react-router-dom'; +import { useParams, Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Typography, @@ -10,14 +10,19 @@ import { Button, TextField, Avatar, - Alert, Paper, CircularProgress, - Container + Container, + Grid, + Chip, + Stack } from '@mui/material'; import api from '../../api'; import { useTitle } from '../../hooks/useTitle'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; +import VerifiedIcon from '@mui/icons-material/Verified'; +import StarIcon from '@mui/icons-material/Star'; interface Reply { id: number; @@ -54,6 +59,7 @@ interface Flavor { const FlavorDetail: React.FC = () => { const { t } = useTranslation(); const { id } = useParams<{ id: string }>(); + const navigate = useNavigate(); const [flavor, setFlavor] = useState(null); const [loading, setLoading] = useState(true); const [replyInputs, setReplyInputs] = useState<{[key: number]: string}>({}); @@ -146,186 +152,237 @@ const FlavorDetail: React.FC = () => { } }; + const handleGoBack = () => { + if (window.history.length > 1) { + navigate(-1); + } else { + navigate(`/category/${flavor?.category_slug}`); + } + }; + if (loading) return ; if (!flavor) return Flavor not found; return ( - - + + {/* Top Bar */} + + + - - {flavor.image_url && ( - + {/* Left: Image */} + + - - - )} - - {!flavor.is_available && ( - - {flavor.is_legacy ? "Unavailable (Legacy Flavor)" : "Out of Stock"} - - )} - - {flavor.name} - - - {flavor.category_name} - - - - - - {(flavor.average_rating || 0).toFixed(1)} / 10 - - + > + {!flavor.is_available && ( + + )} + {flavor.image_url ? ( + + ) : ( + No Image + )} + + - - {flavor.description} - + {/* Right: Info */} + + + + + {flavor.name} + + + + + {(flavor.average_rating || 0).toFixed(1)} + / 10 + + + + {flavor.ratings.length} {t('common.reviews')} + + - {flavor.shop_url && ( - - )} - - + + {flavor.description} + - {/* New Rating Form */} - {currentUser && flavor.user_rating === null && ( - - Rate this flavor -
- - Score (1-10) - setNewScore(val)} size="large" /> - - setNewComment(e.target.value)} - sx={{ - mb: 3, - '& .MuiInputLabel-root': { bgcolor: 'background.paper', px: 0.5 } - }} - InputLabelProps={{ shrink: true }} - /> - - -
- )} + {flavor.shop_url && ( + + )} +
+ + - - {t('home.communityVoice')} - - - {flavor.ratings.length === 0 ? ( - {t('dashboard.noRatings')} - ) : ( - flavor.ratings.map((rating: Rating) => ( - - - {editMode === rating.id ? ( - - setEditScore(val || 0)} size="large" /> - setEditComment(e.target.value)} - label="Your Comment" - sx={{ - '& .MuiInputLabel-root': { bgcolor: 'background.paper', px: 0.5 } - }} - InputLabelProps={{ shrink: true }} - /> - - - - - - ) : ( - <> - - - - {!rating.user_avatar && rating.user.charAt(0).toUpperCase()} - - - - - - {rating.user} - - - - {rating.score}/10 - - - - {new Date(rating.created_at).toLocaleDateString()} - + {/* Reviews Section */} + + + {t('home.communityVoice')} + + + {/* New Rating Form */} + {currentUser && flavor.user_rating === null && ( + + Rate this flavor +
+ + Score + setNewScore(val)} size="large" /> + + setNewComment(e.target.value)} + sx={{ mb: 3, bgcolor: 'background.paper' }} + /> + + +
+ )} + + + {flavor.ratings.length === 0 ? ( + + {t('dashboard.noRatings')} + + ) : ( + flavor.ratings.map((rating: Rating) => ( + + + {editMode === rating.id ? ( + // Edit Mode + + setEditScore(val || 0)} size="large" /> + setEditComment(e.target.value)} + /> + + + - {rating.comment && ( - - {rating.comment} - - )} - - {currentUser === rating.user && ( - <> - - - - )} - - - )} + ) : ( + // View Mode + <> + + + + + {!rating.user_avatar && rating.user.charAt(0).toUpperCase()} + + + + + {rating.user} + + + {new Date(rating.created_at).toLocaleDateString()} + + + + + + {rating.score}/10 + + - - {rating.replies.map((reply: any) => ( - - {reply.user} - {reply.text} - {new Date(reply.created_at).toLocaleDateString()} + {rating.comment && ( + + {rating.comment} + + )} + + + {/* Reply Actions or Metadata */} + + {currentUser === rating.user && ( + + + + + )} + + + )} + + {/* Replies */} + {rating.replies.length > 0 && ( + + {rating.replies.map((reply: any) => ( + + + {reply.user} + {reply.user === rating.user && } + + {reply.text} + + ))} - ))} + )} + {currentUser && ( { fullWidth value={replyInputs[rating.id] || ''} onChange={(e) => setReplyInputs({ ...replyInputs, [rating.id]: e.target.value })} + sx={{ '& .MuiOutlinedInput-root': { bgcolor: 'background.paper' } }} /> )} - - - - )) - )} -
+
+
+ )) + )} + + ); };