Fix claimed items state management and wallpaper display

This commit is contained in:
2025-05-01 08:54:09 -04:00
parent e0a161eb51
commit bb14edf9d9
2 changed files with 135 additions and 116 deletions

View File

@@ -16,6 +16,17 @@ import {
Chip Chip
} from '@mui/material'; } from '@mui/material';
interface Event {
id: number;
title: string;
description: string;
date: string;
location: string;
slug: string;
needed_items?: string[] | string;
wallpaper?: string;
}
const EventDetails: React.FC = () => { const EventDetails: React.FC = () => {
const { slug } = useParams<{ slug: string }>(); const { slug } = useParams<{ slug: string }>();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -66,7 +77,7 @@ const EventDetails: React.FC = () => {
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundImage: 'url(https://www.rydertech.us/backgrounds/space1.jpg)', backgroundImage: event?.wallpaper ? `url(${event.wallpaper})` : 'url(https://www.rydertech.us/backgrounds/space1.jpg)',
backgroundSize: 'cover', backgroundSize: 'cover',
backgroundPosition: 'center', backgroundPosition: 'center',
}} }}
@@ -93,118 +104,128 @@ const EventDetails: React.FC = () => {
} }
return ( return (
<Container maxWidth="md"> <Box
<Paper sx={{ p: 4, mb: 4 }}> sx={{
<Typography variant="h4" component="h1" gutterBottom> minHeight: '100vh',
{event.title} backgroundImage: event.wallpaper ? `url(${event.wallpaper})` : 'url(https://www.rydertech.us/backgrounds/space1.jpg)',
</Typography> backgroundSize: 'cover',
<Typography variant="body1" paragraph> backgroundPosition: 'center',
{event.description} py: 4,
</Typography> }}
<Box sx={{ mb: 3 }}> >
<Typography variant="subtitle1" component="div" gutterBottom> <Container maxWidth="md">
<strong>Date:</strong> {new Date(event.date).toLocaleDateString()} <Paper sx={{ p: 4, mb: 4, backgroundColor: 'rgba(255, 255, 255, 0.95)' }}>
<Typography variant="h4" component="h1" gutterBottom>
{event.title}
</Typography> </Typography>
<Typography variant="subtitle1" component="div"> <Typography variant="body1" paragraph>
<strong>Location:</strong> {event.location} {event.description}
</Typography> </Typography>
{event.needed_items && event.needed_items.length > 0 && ( <Box sx={{ mb: 3 }}>
<Box sx={{ mt: 2 }}> <Typography variant="subtitle1" component="div" gutterBottom>
<Typography variant="subtitle1" component="div" gutterBottom> <strong>Date:</strong> {new Date(event.date).toLocaleDateString()}
<strong>Needed Items:</strong> </Typography>
</Typography> <Typography variant="subtitle1" component="div">
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}> <strong>Location:</strong> {event.location}
{event.needed_items.map((item, index) => ( </Typography>
<Chip key={index} label={item} color="primary" /> {event.needed_items && event.needed_items.length > 0 && (
))} <Box sx={{ mt: 2 }}>
<Typography variant="subtitle1" component="div" gutterBottom>
<strong>Needed Items:</strong>
</Typography>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>
{event.needed_items.map((item, index) => (
<Chip key={index} label={item} color="primary" />
))}
</Box>
</Box> </Box>
</Box> )}
)} </Box>
</Box> <Button
<Button variant="contained"
variant="contained" color="primary"
color="primary" onClick={() => navigate(`/events/${event.slug}/rsvp`)}
onClick={() => navigate(`/events/${event.slug}/rsvp`)} >
> RSVP to Event
RSVP to Event </Button>
</Button> </Paper>
</Paper>
<Paper sx={{ p: 4 }}> <Paper sx={{ p: 4 }}>
<Typography <Typography
variant="h5" variant="h5"
gutterBottom gutterBottom
sx={{ sx={{
fontWeight: 500, fontWeight: 500,
color: 'primary.main', color: 'primary.main',
mb: 2, mb: 2,
borderBottom: '2px solid', borderBottom: '2px solid',
borderColor: 'primary.main', borderColor: 'primary.main',
pb: 1 pb: 1
}} }}
> >
RSVPs RSVPs
</Typography> </Typography>
<List sx={{ <List sx={{
bgcolor: 'rgba(255, 255, 255, 0.1)', bgcolor: 'rgba(255, 255, 255, 0.1)',
borderRadius: 1, borderRadius: 1,
boxShadow: '0 2px 4px rgba(0,0,0,0.05)' boxShadow: '0 2px 4px rgba(0,0,0,0.05)'
}}> }}>
{rsvps.map((rsvp) => ( {rsvps.map((rsvp) => (
<ListItem <ListItem
key={rsvp.id} key={rsvp.id}
sx={{ sx={{
borderBottom: '1px solid', borderBottom: '1px solid',
borderColor: 'divider', borderColor: 'divider',
'&:last-child': { '&:last-child': {
borderBottom: 'none' borderBottom: 'none'
} }
}} }}
> >
<ListItemText <ListItemText
primary={ primary={
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Typography variant="subtitle1" sx={{ fontWeight: 500 }}> <Typography variant="subtitle1" sx={{ fontWeight: 500 }}>
{rsvp.name} {rsvp.name}
</Typography>
<Chip
label={formatAttendingStatus(rsvp.attending)}
color={getStatusColor(rsvp.attending)}
size="small"
/>
</Box>
}
secondary={
<Box sx={{ mt: 1 }}>
{rsvp.bringing_guests === 'yes' && (
<Typography variant="body2" color="text.secondary" paragraph>
Bringing {rsvp.guest_count} guest{rsvp.guest_count !== 1 ? 's' : ''}: {rsvp.guest_names}
</Typography>
)}
{rsvp.items_bringing && rsvp.items_bringing.length > 0 && (
<Typography>
<strong>Items:</strong> {Array.isArray(rsvp.items_bringing) ? rsvp.items_bringing.join(', ') : rsvp.items_bringing}
</Typography>
)}
</Box>
}
/>
</ListItem>
))}
{rsvps.length === 0 && (
<ListItem>
<ListItemText
primary={
<Typography variant="body1" color="text.secondary" align="center">
No RSVPs yet
</Typography> </Typography>
<Chip }
label={formatAttendingStatus(rsvp.attending)} />
color={getStatusColor(rsvp.attending)} </ListItem>
size="small" )}
/> </List>
</Box> </Paper>
} </Container>
secondary={ </Box>
<Box sx={{ mt: 1 }}>
{rsvp.bringing_guests === 'yes' && (
<Typography variant="body2" color="text.secondary" paragraph>
Bringing {rsvp.guest_count} guest{rsvp.guest_count !== 1 ? 's' : ''}: {rsvp.guest_names}
</Typography>
)}
{rsvp.items_bringing && rsvp.items_bringing.length > 0 && (
<Typography>
<strong>Items:</strong> {Array.isArray(rsvp.items_bringing) ? rsvp.items_bringing.join(', ') : rsvp.items_bringing}
</Typography>
)}
</Box>
}
/>
</ListItem>
))}
{rsvps.length === 0 && (
<ListItem>
<ListItemText
primary={
<Typography variant="body1" color="text.secondary" align="center">
No RSVPs yet
</Typography>
}
/>
</ListItem>
)}
</List>
</Paper>
</Container>
); );
}; };

View File

@@ -90,9 +90,8 @@ const EventView: React.FC = () => {
itemsBringing = rsvp.items_bringing; itemsBringing = rsvp.items_bringing;
} }
if (itemsBringing.length > 0) { // Add items to claimed set
itemsBringing.forEach(item => claimed.add(item)); itemsBringing.forEach(item => claimed.add(item));
}
} catch (e) { } catch (e) {
console.error('Error processing items for RSVP:', e); console.error('Error processing items for RSVP:', e);
} }
@@ -103,12 +102,11 @@ const EventView: React.FC = () => {
}; };
}); });
// Filter out claimed items from needed items // Update state with processed data
const availableItems = items.filter(item => !claimed.has(item));
setNeededItems(availableItems);
setClaimedItems(Array.from(claimed));
setRsvps(processedRsvps); setRsvps(processedRsvps);
setClaimedItems(Array.from(claimed));
// Filter needed items to only show unclaimed ones
setNeededItems(items.filter(item => !claimed.has(item)));
setLoading(false); setLoading(false);
} catch (error) { } catch (error) {
setError('Failed to load event data'); setError('Failed to load event data');