fixed dashboard sizing on mobile

This commit is contained in:
nvrl committed 2026-02-18 06:04:46 +01:00
1 parent 4318eed372
commit a810d21557
4 files changed
+115 -83

No files matched your search

+1 -1
View File
@@ -481,7 +481,7 @@ const App: React.FC = () => {
onClose={() => setNotifAnchorEl(null)}
elevation={3}
sx={{ mt: 1 }}
PaperProps={{ sx: { width: 320, maxHeight: 400 } }}
PaperProps={{ sx: { width: 320, maxHeight: 400, borderRadius: 1 } }}
>
<Box sx={{ p: 1.5, display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: '1px solid', borderColor: 'divider' }}>
<Typography variant="subtitle2" sx={{ fontWeight: 'bold' }}>Notifications</Typography>
+9 -6
View File
@@ -14,16 +14,17 @@ const RatingBadge: React.FC<RatingBadgeProps> = ({ score, size = 'medium', sx })
return (
<Box sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'baseline',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: 0.5,
bgcolor: 'primary.main',
color: 'primary.contrastText',
px: isLarge ? 2 : (isSmall ? 1 : 1.5),
py: isLarge ? 0.8 : (isSmall ? 0.3 : 0.5),
borderRadius: 1.5,
py: isLarge ? 0.5 : (isSmall ? 0.2 : 0.4),
borderRadius: 2,
minWidth: 'fit-content',
height: 'fit-content',
boxShadow: theme.palette.mode === 'dark'
? '0 4px 12px rgba(0,0,0,0.4)'
: '0 2px 8px rgba(0,0,0,0.1)',
@@ -31,7 +32,7 @@ const RatingBadge: React.FC<RatingBadgeProps> = ({ score, size = 'medium', sx })
}}>
<Typography
variant={isLarge ? "h5" : (isSmall ? "caption" : "subtitle1")}
sx={{ fontWeight: '900', lineHeight: 1 }}
sx={{ fontWeight: '900', lineHeight: 1, display: 'flex', alignItems: 'center' }}
>
{typeof score === 'number' ? (isLarge ? score.toFixed(1) : score.toFixed(0)) : score}
</Typography>
@@ -41,6 +42,8 @@ const RatingBadge: React.FC<RatingBadgeProps> = ({ score, size = 'medium', sx })
fontSize: isLarge ? '0.75rem' : (isSmall ? '0.55rem' : '0.65rem'),
fontWeight: '900',
opacity: 0.9,
lineHeight: 1,
mt: 0.2
}}
>
/ 10
+10 -7
View File
@@ -299,12 +299,12 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
<RichText text={rating.comment} />
</Typography>
) : (
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic' }}>{t('dashboard.noRatings')}</Typography>
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic' }}>No comment provided.</Typography>
)}
</Box>
<Link to={`/flavor/${rating.flavor}`} style={{ flexShrink: 0 }}>
<Box sx={{ width: 70, height: 70, borderRadius: 2, overflow: 'hidden', bgcolor: 'action.hover', border: '1px solid', borderColor: 'divider' }}>
<Box component="img" src={rating.flavor_image || undefined} sx={{ width: '100%', height: '100%', objectFit: 'contain', p: 0.5 }} />
<Box sx={{ width: 70, height: 70, borderRadius: 1, overflow: 'hidden', bgcolor: 'background.default', border: '1px solid', borderColor: 'divider' }}>
<Box component="img" src={rating.flavor_image || undefined} sx={{ width: '100%', height: '100%', objectFit: 'cover' }} />
</Box>
</Link>
</Box>
@@ -376,7 +376,7 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
{/* Notifications Widget */}
<Card elevation={0} sx={{ borderRadius: 4, border: '1px solid', borderColor: 'divider' }}>
<Card elevation={0} sx={{ borderRadius: 1, border: '1px solid', borderColor: 'divider' }}>
<Box sx={{ p: 2, borderBottom: '1px solid', borderColor: 'divider', bgcolor: alpha('#000', 0.02), display: 'flex', alignItems: 'center', gap: 1 }}>
<NotificationsIcon color="primary" fontSize="small" />
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>{t('community.notifications')}</Typography>
@@ -406,7 +406,7 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
</Card>
{/* Following Widget */}
<Card elevation={0} sx={{ borderRadius: 4, border: '1px solid', borderColor: 'divider' }}>
<Card elevation={0} sx={{ borderRadius: 1, border: '1px solid', borderColor: 'divider' }}>
<Box sx={{ p: 2, borderBottom: '1px solid', borderColor: 'divider', bgcolor: alpha('#000', 0.02), display: 'flex', alignItems: 'center', gap: 1 }}>
<PeopleIcon color="primary" fontSize="small" />
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>{t('nav.following')}</Typography>
@@ -417,6 +417,7 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
value={followingSearch}
onChange={(e) => setFollowingSearch(e.target.value)}
InputProps={{ startAdornment: <SearchIcon fontSize="small" sx={{ mr: 1, color: 'text.secondary' }} /> }}
sx={{ '& .MuiOutlinedInput-root': { borderRadius: 1 } }}
/>
</Box>
<List disablePadding sx={{ maxHeight: 250, overflowY: 'auto' }}>
@@ -430,7 +431,7 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
</Card>
{/* Top Rated by Circle */}
<Card elevation={0} sx={{ borderRadius: 4, border: '1px solid', borderColor: 'divider' }}>
<Card elevation={0} sx={{ borderRadius: 1, border: '1px solid', borderColor: 'divider' }}>
<Box sx={{ p: 2, borderBottom: '1px solid', borderColor: 'divider', bgcolor: alpha('#000', 0.02), display: 'flex', alignItems: 'center', gap: 1 }}>
<WhatshotIcon color="error" fontSize="small" />
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>{t('community.topRated')}</Typography>
@@ -439,7 +440,9 @@ const CommunityFeed: React.FC<CommunityFeedProps> = ({ adminMode }) => {
{topFollowed.map((flavor, idx) => (
<ListItemButton key={flavor.id} component={Link} to={`/flavor/${flavor.id}`}>
<Box sx={{ mr: 2, fontWeight: 'bold', color: 'text.secondary', width: 15 }}>{idx + 1}</Box>
<Avatar src={flavor.image_url} variant="rounded" sx={{ width: 32, height: 32, mr: 2, bgcolor: 'transparent' }} imgProps={{ sx: { objectFit: 'contain' } }} />
<Box sx={{ width: 32, height: 32, mr: 2, bgcolor: 'background.default', border: '1px solid', borderColor: 'divider', borderRadius: 0.5, overflow: 'hidden', flexShrink: 0 }}>
<Box component="img" src={flavor.image_url} sx={{ width: '100%', height: '100%', objectFit: 'cover' }} />
</Box>
<ListItemText
primary={flavor.name}
primaryTypographyProps={{ variant: 'body2', fontWeight: 'bold', noWrap: true }}
+95 -69
View File
@@ -18,10 +18,10 @@ import {
Chip,
Collapse,
TextField,
InputAdornment,
Tooltip
} from '@mui/material';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
InputAdornment,
Tooltip,
useMediaQuery
} from '@mui/material';import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import ShareIcon from '@mui/icons-material/Share';
import CommentIcon from '@mui/icons-material/Comment';
import VerifiedIcon from '@mui/icons-material/Verified';
@@ -47,6 +47,7 @@ const Dashboard: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
useTitle(t('nav.dashboard'));
const [data, setData] = useState<DashboardData | null>(null);
const [loading, setLoading] = useState(true);
@@ -255,43 +256,56 @@ const Dashboard: React.FC = () => {
{/* TAB 0: MY REVIEWS */}
{activeTab === 0 && (
<Box>
<Stack direction={{ xs: 'column', md: 'row' }} spacing={1.5} sx={{ mb: 4, alignItems: { xs: 'stretch', md: 'center' } }}>
<Box sx={{ flexGrow: 1, minWidth: { md: 300 } }}>
{/* Filter Controls for Reviews */}
<Grid container spacing={2} sx={{ mb: 4, alignItems: 'center' }}>
<Grid size={{ xs: 12, md: 4, lg: 5 }}>
<TextField
fullWidth size="small" placeholder={t('dashboard.searchRated')}
value={ratedSearch} onChange={e => setRatedSearch(e.target.value)}
slotProps={{ input: { startAdornment: <InputAdornment position="start"><SearchIcon fontSize="small" /></InputAdornment> } }}
sx={{ bgcolor: 'background.paper', borderRadius: 1, '& .MuiOutlinedInput-root': { borderRadius: 1, height: 40 } }}
sx={{
bgcolor: 'background.paper',
borderRadius: 1,
'& .MuiOutlinedInput-root': { borderRadius: 1, height: 44 }
}}
/>
</Box>
<Stack direction="row" spacing={0.8} sx={{ overflowX: 'auto', py: 0.5, '&::-webkit-scrollbar': { display: 'none' }, flexShrink: 0 }}>
{ratedCategories.map(cat => (
<Chip
key={cat} label={cat === 'All' ? t('nav.home').replace('Home', 'All') : t(`categories.${data.my_ratings.find(r => r.category_name === cat)?.category_slug}`, { defaultValue: cat })}
onClick={() => setRatedCategory(cat)}
color={ratedCategory === cat ? 'primary' : 'default'}
variant={ratedCategory === cat ? 'filled' : 'outlined'}
sx={{ fontWeight: 'bold', height: 32, px: 0.5, borderRadius: 1, fontSize: '0.8rem' }}
/>
))}
</Stack>
<Stack direction="row" spacing={0.5} sx={{ bgcolor: 'background.paper', p: 0.5, borderRadius: 1, border: '1px solid', borderColor: 'divider', height: 40, alignItems: 'center' }}>
<Button
size="small" variant={ratedSort === 'date' ? 'contained' : 'text'}
onClick={() => setRatedSort('date')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 30, px: 2, fontSize: '0.8rem' }}
>
{t('dashboard.date')}
</Button>
<Button
size="small" variant={ratedSort === 'rating' ? 'contained' : 'text'}
onClick={() => setRatedSort('rating')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 30, px: 2, fontSize: '0.8rem' }}
>
{t('dashboard.rating')}
</Button>
</Stack>
</Stack>
</Grid>
<Grid size={{ xs: 12, md: 'auto' }} sx={{ flexGrow: 1, overflow: 'hidden' }}>
<Stack direction="row" spacing={1} sx={{ overflowX: 'auto', py: 0.5, px: 0.5, '&::-webkit-scrollbar': { display: 'none' } }}>
{ratedCategories.map(cat => (
<Chip
key={cat} label={cat === 'All' ? t('nav.home').replace('Home', 'All') : t(`categories.${data.my_ratings.find(r => r.category_name === cat)?.category_slug}`, { defaultValue: cat })}
onClick={() => setRatedCategory(cat)}
color={ratedCategory === cat ? 'primary' : 'default'}
variant={ratedCategory === cat ? 'filled' : 'outlined'}
sx={{ fontWeight: 'bold', height: 36, px: 0.5, borderRadius: 1, fontSize: '0.85rem' }}
/>
))}
</Stack>
</Grid>
<Grid size={{ xs: 12, md: 'auto' }}>
<Stack direction="row" spacing={0.5} sx={{ bgcolor: 'background.paper', p: 0.5, borderRadius: 1, border: '1px solid', borderColor: 'divider', height: 44, width: { xs: '100%', md: 'auto' } }}>
<Button
fullWidth={isMobile}
size="small" variant={ratedSort === 'date' ? 'contained' : 'text'}
onClick={() => setRatedSort('date')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 34, fontSize: '0.85rem' }}
>
{t('dashboard.date')}
</Button>
<Button
fullWidth={isMobile}
size="small" variant={ratedSort === 'rating' ? 'contained' : 'text'}
onClick={() => setRatedSort('rating')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 34, fontSize: '0.85rem' }}
>
{t('dashboard.rating')}
</Button>
</Stack>
</Grid>
</Grid>
<Stack spacing={3}>
{filteredAndSortedRated.length === 0 ? (
@@ -416,44 +430,56 @@ const Dashboard: React.FC = () => {
{/* TAB 1: EXPLORE NEW */}
{activeTab === 1 && (
<Box>
{/* Filter Controls */}
<Stack direction={{ xs: 'column', md: 'row' }} spacing={1.5} sx={{ mb: 4, alignItems: { xs: 'stretch', md: 'center' } }}>
<Box sx={{ flexGrow: 1, minWidth: { md: 300 } }}>
{/* Filter Controls for Explore */}
<Grid container spacing={2} sx={{ mb: 4, alignItems: 'center' }}>
<Grid size={{ xs: 12, md: 4, lg: 5 }}>
<TextField
fullWidth size="small" placeholder={t('dashboard.searchMissing')}
value={exploreSearch} onChange={e => setExploreSearch(e.target.value)}
slotProps={{ input: { startAdornment: <InputAdornment position="start"><SearchIcon fontSize="small" /></InputAdornment> } }}
sx={{ bgcolor: 'background.paper', borderRadius: 1, '& .MuiOutlinedInput-root': { borderRadius: 1, height: 40 } }}
sx={{
bgcolor: 'background.paper',
borderRadius: 1,
'& .MuiOutlinedInput-root': { borderRadius: 1, height: 44 }
}}
/>
</Box>
<Stack direction="row" spacing={0.8} sx={{ overflowX: 'auto', py: 0.5, '&::-webkit-scrollbar': { display: 'none' }, flexShrink: 0 }}>
{exploreCategories.map(cat => (
<Chip
key={cat} label={cat === 'All' ? t('nav.home').replace('Home', 'All') : t(`categories.${data.missing_flavors.find(f => f.category_name === cat)?.category_slug}`, { defaultValue: cat })}
onClick={() => setExploreCategory(cat)}
color={exploreCategory === cat ? 'primary' : 'default'}
variant={exploreCategory === cat ? 'filled' : 'outlined'}
sx={{ fontWeight: 'bold', height: 32, px: 0.5, borderRadius: 1, fontSize: '0.8rem' }}
/>
))}
</Stack>
<Stack direction="row" spacing={0.5} sx={{ bgcolor: 'background.paper', p: 0.5, borderRadius: 1, border: '1px solid', borderColor: 'divider', height: 40, alignItems: 'center' }}>
<Button
size="small" variant={exploreSort === 'community' ? 'contained' : 'text'}
onClick={() => setExploreSort('community')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 30, px: 2, fontSize: '0.8rem' }}
>
{t('dashboard.communityRating')}
</Button>
<Button
size="small" variant={exploreSort === 'circle' ? 'contained' : 'text'}
onClick={() => setExploreSort('circle')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 30, px: 2, fontSize: '0.8rem' }}
>
{t('dashboard.circleRating')}
</Button>
</Stack>
</Stack>
</Grid>
<Grid size={{ xs: 12, md: 'auto' }} sx={{ flexGrow: 1, overflow: 'hidden' }}>
<Stack direction="row" spacing={1} sx={{ overflowX: 'auto', py: 0.5, px: 0.5, '&::-webkit-scrollbar': { display: 'none' } }}>
{exploreCategories.map(cat => (
<Chip
key={cat} label={cat === 'All' ? t('nav.home').replace('Home', 'All') : t(`categories.${data.missing_flavors.find(f => f.category_name === cat)?.category_slug}`, { defaultValue: cat })}
onClick={() => setExploreCategory(cat)}
color={exploreCategory === cat ? 'primary' : 'default'}
variant={exploreCategory === cat ? 'filled' : 'outlined'}
sx={{ fontWeight: 'bold', height: 36, px: 0.5, borderRadius: 1, fontSize: '0.85rem' }}
/>
))}
</Stack>
</Grid>
<Grid size={{ xs: 12, md: 'auto' }}>
<Stack direction="row" spacing={0.5} sx={{ bgcolor: 'background.paper', p: 0.5, borderRadius: 1, border: '1px solid', borderColor: 'divider', height: 44, width: { xs: '100%', md: 'auto' } }}>
<Button
fullWidth={isMobile}
size="small" variant={exploreSort === 'community' ? 'contained' : 'text'}
onClick={() => setExploreSort('community')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 34, px: 2, fontSize: '0.85rem' }}
>
{t('dashboard.communityRating')}
</Button>
<Button
fullWidth={isMobile}
size="small" variant={exploreSort === 'circle' ? 'contained' : 'text'}
onClick={() => setExploreSort('circle')}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 0.8, height: 34, px: 2, fontSize: '0.85rem' }}
>
{t('dashboard.circleRating')}
</Button>
</Stack>
</Grid>
</Grid>
{filteredMissing.length === 0 ? (
<Box sx={{ py: 10, textAlign: 'center' }}>