Fix: Add type safety and improve items handling in both components

This commit is contained in:
2025-04-30 11:05:46 -04:00
parent 7522b04334
commit c0554d2575
3 changed files with 58 additions and 32 deletions

View File

@@ -198,10 +198,22 @@ const EventAdmin: React.FC = () => {
if (!rsvpToEdit) return; if (!rsvpToEdit) return;
try { try {
await axios.put(`/api/events/${slug}/rsvps/${rsvpToEdit.id}`, editForm); const submissionData = {
...editForm,
items_bringing: JSON.stringify(editForm.items_bringing)
};
await axios.put(`/api/events/${slug}/rsvps/${rsvpToEdit.id}`, submissionData);
// Update the local state // Update the local state
const updatedRsvps = rsvps.map((r: RSVP) => r.id === rsvpToEdit.id ? { ...r, ...editForm } : r); const updatedRsvps = rsvps.map((r: RSVP) =>
r.id === rsvpToEdit.id
? {
...r,
...editForm,
items_bringing: editForm.items_bringing // Keep as array in local state
}
: r
);
// Recalculate claimed items // Recalculate claimed items
const claimed = new Set<string>(); const claimed = new Set<string>();
@@ -222,6 +234,7 @@ const EventAdmin: React.FC = () => {
: []; : [];
} catch (e) { } catch (e) {
console.error('Error parsing event needed_items:', e); console.error('Error parsing event needed_items:', e);
allItems = [];
} }
} }
@@ -346,12 +359,23 @@ const EventAdmin: React.FC = () => {
</TableCell> </TableCell>
<TableCell> <TableCell>
{(() => { {(() => {
const items = typeof rsvp.items_bringing === 'string' const items = Array.isArray(rsvp.items_bringing)
? JSON.parse(rsvp.items_bringing) ? rsvp.items_bringing
: Array.isArray(rsvp.items_bringing) : typeof rsvp.items_bringing === 'string'
? rsvp.items_bringing ? JSON.parse(rsvp.items_bringing)
: []; : [];
return items.join(', '); return (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
{items.map((item, index) => (
<Chip
key={index}
label={item}
color="primary"
size="small"
/>
))}
</Box>
);
})()} })()}
</TableCell> </TableCell>
<TableCell> <TableCell>
@@ -474,7 +498,7 @@ const EventAdmin: React.FC = () => {
</Box> </Box>
)} )}
> >
{[...new Set([...neededItems, ...editForm.items_bringing])].map((item) => ( {Array.from(new Set([...neededItems, ...editForm.items_bringing])).map((item) => (
<MenuItem key={item} value={item}> <MenuItem key={item} value={item}>
<Checkbox checked={editForm.items_bringing.includes(item)} /> <Checkbox checked={editForm.items_bringing.includes(item)} />
<ListItemText <ListItemText

View File

@@ -16,6 +16,7 @@ import {
Checkbox, Checkbox,
ListItemText, ListItemText,
OutlinedInput, OutlinedInput,
Chip,
} from '@mui/material'; } from '@mui/material';
interface RSVPFormData { interface RSVPFormData {
@@ -51,7 +52,6 @@ const RSVPForm: React.FC = () => {
axios.get(`/api/events/${slug}`), axios.get(`/api/events/${slug}`),
axios.get(`/api/events/${slug}/rsvps`) axios.get(`/api/events/${slug}/rsvps`)
]); ]);
console.log('API Response:', eventResponse.data);
// Process needed items // Process needed items
let items: string[] = []; let items: string[] = [];
@@ -86,7 +86,6 @@ const RSVPForm: React.FC = () => {
// Filter out claimed items // Filter out claimed items
const availableItems = items.filter(item => !claimed.has(item)); const availableItems = items.filter(item => !claimed.has(item));
console.log('Available items:', availableItems);
setNeededItems(availableItems); setNeededItems(availableItems);
setClaimedItems(Array.from(claimed)); setClaimedItems(Array.from(claimed));
} catch (error) { } catch (error) {
@@ -98,10 +97,6 @@ const RSVPForm: React.FC = () => {
fetchEventDetails(); fetchEventDetails();
}, [slug]); }, [slug]);
useEffect(() => {
console.log('Current neededItems state:', neededItems);
}, [neededItems]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target; const { name, value } = e.target;
setFormData(prev => ({ setFormData(prev => ({
@@ -119,14 +114,8 @@ const RSVPForm: React.FC = () => {
}; };
const handleItemsChange = (e: SelectChangeEvent<string[]>) => { const handleItemsChange = (e: SelectChangeEvent<string[]>) => {
const value = e.target.value; const { value } = e.target;
console.log('Select onChange value:', value); const itemsArray = Array.isArray(value) ? value : [];
const itemsArray = Array.isArray(value)
? value
: typeof value === 'string'
? value.split(',').map((item: string): string => item.trim())
: [];
console.log('Processed items array:', itemsArray);
setFormData(prev => ({ setFormData(prev => ({
...prev, ...prev,
items_bringing: itemsArray items_bringing: itemsArray
@@ -139,7 +128,11 @@ const RSVPForm: React.FC = () => {
setError(null); setError(null);
try { try {
await axios.post(`/api/events/${slug}/rsvp`, formData); const submissionData = {
...formData,
items_bringing: JSON.stringify(formData.items_bringing)
};
await axios.post(`/api/events/${slug}/rsvp`, submissionData);
setSuccess(true); setSuccess(true);
} catch (err) { } catch (err) {
setError('Failed to submit RSVP. Please try again.'); setError('Failed to submit RSVP. Please try again.');
@@ -256,17 +249,20 @@ const RSVPForm: React.FC = () => {
<Select <Select
multiple multiple
name="items_bringing" name="items_bringing"
value={Array.isArray(formData.items_bringing) ? formData.items_bringing : []} value={formData.items_bringing}
onChange={handleItemsChange} onChange={handleItemsChange}
input={<OutlinedInput label="What items are you bringing?" />} input={<OutlinedInput label="What items are you bringing?" />}
renderValue={(selected) => { renderValue={(selected) => (
if (!Array.isArray(selected) || selected.length === 0) return ''; <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
return selected.join(', '); {selected.map((value) => (
}} <Chip key={value} label={value} />
))}
</Box>
)}
> >
{neededItems.map((item) => ( {neededItems.map((item) => (
<MenuItem key={item} value={item}> <MenuItem key={item} value={item}>
<Checkbox checked={Array.isArray(formData.items_bringing) && formData.items_bringing.includes(item)} /> <Checkbox checked={formData.items_bringing.includes(item)} />
<ListItemText primary={item} /> <ListItemText primary={item} />
</MenuItem> </MenuItem>
))} ))}

View File

@@ -1,7 +1,11 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@@ -16,5 +20,7 @@
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx"
}, },
"include": ["src"] "include": [
"src"
]
} }