-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(all): add events collection. Home page based on
user.role
(#…
…14) - **Refactored `Home`**: - Adjusted logic to render `DonorDashboard` or `OrganizationDashboard` based on `user.role`. - **Firebase Updates**: - Added an `events` collection to centralize event management. - Updated the user schema: - Added `joinedEvents` as an array of event IDs for both `DonorProfile` and `OrganizationProfile`. - **Component Updates**: - Updated `DonationModal` to align with the new `DonationEvent` schema (1:1 relationship between donor and event). - Enhanced `Schedule` to fetch and display events dynamically, adding visual indicators for event dates on the calendar. - **Hook Improvements**: - Enhanced `useEvents` to handle creating, updating, and deleting events in the `events` collection. - Streamlined `useUser` for role-based event logic. - **Type Updates**: - Simplified and refined the `DonationEvent` type for better clarity and alignment with the new schema. ### Breaking Changes: - Migrated to a centralized `events` collection; users now reference events via `joinedEvents`. --------- Co-authored-by: MC2b6 <[email protected]>
- Loading branch information
1 parent
afec091
commit 22e849c
Showing
30 changed files
with
1,373 additions
and
1,204 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
import { useState } from 'react'; | ||
import { | ||
Modal, | ||
Box, | ||
Typography, | ||
Button, | ||
RadioGroup, | ||
FormControlLabel, | ||
Radio, | ||
Divider, | ||
} from '@mui/material'; | ||
import { LocalizationProvider, DateTimePicker } from '@mui/x-date-pickers'; | ||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | ||
import type dayjs from 'dayjs'; | ||
|
||
import { useEvents } from '@/hooks'; | ||
|
||
import { MessageDialog } from '@/components/common'; | ||
|
||
interface DonationModalProps { | ||
open: boolean; | ||
onClose: () => void; | ||
organization: OrganizationProfile; | ||
selectedNeeds: string[]; | ||
donor: DonorProfile; | ||
} | ||
|
||
const DonationModal = ({ | ||
open, | ||
onClose, | ||
organization, | ||
selectedNeeds, | ||
donor, | ||
}: DonationModalProps) => { | ||
const [method, setMethod] = useState<string>('drop-off'); | ||
const [selectedTime, setSelectedTime] = useState<dayjs.Dayjs | null>(null); | ||
const [openMessageDialog, setOpenMessageDialog] = useState(false); | ||
const [message, setMessage] = useState<string>(''); | ||
const { addOrUpdateEvent } = useEvents(); | ||
|
||
const handleConfirm = async () => { | ||
if (selectedNeeds.length === 0 || !selectedTime || !method) { | ||
setMessage('Please fill out all fields and select at least one need.'); | ||
setOpenMessageDialog(true); | ||
return; | ||
} | ||
|
||
const newEvent: DonationEvent = { | ||
eventId: `${organization.uid}-${donor.uid}-${new Date().toISOString()}`, // Unique ID | ||
organizationId: organization.uid, | ||
donorId: donor.uid, | ||
title: `Donation to ${organization.name}`, | ||
description: `Donation of items: ${selectedNeeds.join(', ')}`, | ||
date: selectedTime!.toDate(), // Ensure selectedTime is not null | ||
supplies: selectedNeeds.map( | ||
(item) => | ||
({ | ||
itemName: item, | ||
quantityNeeded: 1, // Default assumption | ||
quantityProvided: 1, // Donor provides these items | ||
providedBy: [donor.uid], // Add the donor ID | ||
status: true, | ||
}) as Supply | ||
), | ||
}; | ||
|
||
try { | ||
// Add or update the event using the useEvents hook | ||
await addOrUpdateEvent(newEvent); | ||
|
||
setMessage('Donation successfully added to your schedule!'); | ||
setOpenMessageDialog(true); | ||
onClose(); // Close the modal | ||
} catch (error) { | ||
console.error('Error adding/updating event:', error); | ||
setMessage('Failed to schedule donation. Please try again.'); | ||
setOpenMessageDialog(true); | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<Modal | ||
open={open} | ||
onClose={onClose} | ||
disableEnforceFocus | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
margin: 5, | ||
}} | ||
> | ||
<Box | ||
sx={{ | ||
position: 'absolute', | ||
top: '50%', | ||
left: '50%', | ||
transform: 'translate(-50%, -50%)', | ||
bgcolor: 'background.paper', | ||
boxShadow: 24, | ||
p: 4, | ||
borderRadius: 3, | ||
width: '90%', | ||
maxWidth: 500, | ||
}} | ||
> | ||
<Typography | ||
variant='h6' | ||
fontWeight='bold' | ||
mb={3} | ||
textAlign='center' | ||
> | ||
Schedule Your Donation | ||
</Typography> | ||
<Divider sx={{ mb: 3 }} /> | ||
<Box sx={{ mb: 3 }}> | ||
<Typography | ||
variant='subtitle1' | ||
fontWeight='bold' | ||
mb={1} | ||
> | ||
Select a Delivery Method: | ||
</Typography> | ||
<RadioGroup | ||
value={method} | ||
onChange={(e) => setMethod(e.target.value)} | ||
> | ||
<FormControlLabel | ||
value='drop-off' | ||
control={<Radio />} | ||
label='Drop-off' | ||
/> | ||
{organization.pickup && ( | ||
<FormControlLabel | ||
value='pick-up' | ||
control={<Radio />} | ||
label='Pick-up' | ||
/> | ||
)} | ||
</RadioGroup> | ||
</Box> | ||
<Box sx={{ mb: 3 }}> | ||
<Typography | ||
variant='subtitle1' | ||
fontWeight='bold' | ||
mb={1} | ||
> | ||
Select a Time: | ||
</Typography> | ||
<LocalizationProvider dateAdapter={AdapterDayjs}> | ||
<DateTimePicker | ||
value={selectedTime} | ||
onChange={setSelectedTime} | ||
slotProps={{ | ||
textField: { | ||
fullWidth: true, | ||
sx: { | ||
'& .MuiInputBase-root': { | ||
fontSize: '1rem', | ||
}, | ||
}, | ||
}, | ||
}} | ||
/> | ||
</LocalizationProvider> | ||
</Box> | ||
<Divider sx={{ mb: 3 }} /> | ||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}> | ||
<Button | ||
onClick={onClose} | ||
color='secondary' | ||
size='large' | ||
sx={{ px: 3 }} | ||
> | ||
Cancel | ||
</Button> | ||
<Button | ||
onClick={handleConfirm} | ||
variant='contained' | ||
size='large' | ||
sx={{ px: 3 }} | ||
> | ||
Confirm | ||
</Button> | ||
</Box> | ||
</Box> | ||
</Modal> | ||
|
||
<MessageDialog | ||
open={openMessageDialog} | ||
onClose={() => setOpenMessageDialog(false)} | ||
message={message} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default DonationModal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { | ||
List, | ||
ListItem, | ||
Checkbox, | ||
ListItemText, | ||
Typography, | ||
} from '@mui/material'; | ||
|
||
interface NeedsListProps { | ||
needs: string[]; | ||
checkedItems: boolean[]; | ||
onToggle: (index: number) => void; | ||
} | ||
|
||
const NeedsList = ({ needs, checkedItems, onToggle }: NeedsListProps) => ( | ||
<List> | ||
{needs.length > 0 ? ( | ||
needs.map((need, index) => ( | ||
<ListItem key={index}> | ||
<Checkbox | ||
checked={checkedItems[index]} | ||
onChange={() => onToggle(index)} | ||
/> | ||
<ListItemText primary={need} /> | ||
</ListItem> | ||
)) | ||
) : ( | ||
<Typography | ||
variant='body1' | ||
color='text.secondary' | ||
m={2} | ||
> | ||
No current needs. | ||
</Typography> | ||
)} | ||
</List> | ||
); | ||
|
||
export default NeedsList; |
Oops, something went wrong.