Fix: Add type safety and improve items handling in both components
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user