Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(time-preferences): add time grid for users to select study time … #6

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import GroupsPage from '@components/GroupsPage';
import HomePage from '@components/HomePage';
import EditProfile from '@components/Profile/EditProfile';
import ProfilePage from '@components/Profile/ProfilePage';
import TimePreferencesPage from '@components/Profile/TimePreferencesPage';
import { ThemeProvider } from '@mui/material/styles';
import { theme } from '@utils/theme';
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
Expand All @@ -25,6 +26,7 @@ const AppContent = ({ currentPage, setCurrentPage }) => {
{/* <Route path="messages" element={<div>TBD</div>} /> */}
<Route path="profile/:id" element={<ProfilePage />} />
<Route path="edit-profile" element={<EditProfile />} />
<Route path="time-preferences" element={<TimePreferencesPage />} />
</Routes>
</div>
{!isEditProfilePage && <Footer currentPage={currentPage} setCurrentPage={setCurrentPage} />}
Expand Down
24 changes: 20 additions & 4 deletions src/components/Profile/ProfilePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export default function ProfilePage() {
setSignOutDialogOpen(true);
};

const handleTimePreferencesClick = () => {
navigate('/time-preferences'); // Navigates to the Time Preferences page
};

if (loading) {
return <CircularProgress />;
}
Expand Down Expand Up @@ -81,7 +85,11 @@ export default function ProfilePage() {
/>
</InfoSection>

<ActionButtons onEditClick={handleEditClick} onSignOutClick={handleSignOutDialogOpen} />
<ActionButtons
onEditClick={handleEditClick}
onSignOutClick={handleSignOutDialogOpen}
onTimePreferencesClick={handleTimePreferencesClick}
/>
<SignOutDialog open={signOutDialogOpen} onClose={() => setSignOutDialogOpen(false)} />
</Box>
);
Expand Down Expand Up @@ -139,7 +147,7 @@ const ContentBox = ({ icon: IconComponent, title, content, isCourses = false })

const CustomDivider = () => <Divider sx={{ my: 1 }} />;

const ActionButtons = ({ onEditClick, onSignOutClick }) => (
const ActionButtons = ({ onEditClick, onSignOutClick, onTimePreferencesClick }) => (
<Box
sx={{
display: 'flex',
Expand All @@ -149,13 +157,21 @@ const ActionButtons = ({ onEditClick, onSignOutClick }) => (
mt: 4,
}}
>
<Button variant="contained" onClick={onEditClick} sx={{ mb: 2, width: '150px' }}>
<Button variant="contained" onClick={onEditClick} sx={{ mb: 2, width: '250px' }}>
Edit Profile
</Button>
<Button
variant="contained"
color="primary"
sx={{ mb: 2, width: '250px' }}
onClick={onTimePreferencesClick}
>
Time Preferences
</Button>
<Button
variant="contained"
color="secondary"
sx={{ width: '150px', backgroundColor: 'secondary.main' }}
sx={{ width: '150px', backgroundColor: 'secondary.main', mt: 2 }}
onClick={onSignOutClick}
>
Sign Out
Expand Down
160 changes: 160 additions & 0 deletions src/components/Profile/TimePreferencesGrid.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { useState } from 'react';

import {
Box,
Paper,
Typography,
Select,
MenuItem,
FormControl,
InputLabel,
Switch,
FormControlLabel,
useTheme,
} from '@mui/material';

// Generate 12-hour clock with AM/PM
const hours = Array.from({ length: 24 }, (_, i) => {
const hour = i % 12 || 12;
return `${hour} ${i < 12 ? 'AM' : 'PM'}`;
});

const weekdays = ['M', 'T', 'W', 'Th', 'F'];
const weekendDays = ['Sa', 'Su'];

const TimePreferencesGrid = ({ selectedTimes, setSelectedTimes }) => {
const [noEarlierThan, setNoEarlierThan] = useState(8); // Time index for "No earlier than"
const [noLaterThan, setNoLaterThan] = useState(20); // Time index for "No later than"
const [includeWeekends, setIncludeWeekends] = useState(false); // Toggle for showing weekends

const handleSlotClick = (day, hour) => {
const slot = `${day}-${hour}`;
setSelectedTimes((prev) =>
prev.includes(slot) ? prev.filter((time) => time !== slot) : [...prev, slot],
);
};

const theme = useTheme();

// Handle filtering the displayed hours based on the selected limits
const filteredHours = hours.slice(noEarlierThan, noLaterThan + 1);

return (
<Box sx={{ maxWidth: 800, margin: 'auto', padding: 3 }}>
{/* No Earlier Than and No Later Than selectors */}
<Box sx={{ display: 'flex', justifyContent: 'space-between', marginBottom: 2 }}>
<FormControl sx={{ minWidth: 120 }}>
<InputLabel>No earlier than</InputLabel>
<Select
value={noEarlierThan}
label="No earlier than"
onChange={(e) => setNoEarlierThan(e.target.value)}
>
{hours.map((hour, index) => (
<MenuItem key={hour} value={index}>
{hour}
</MenuItem>
))}
</Select>
</FormControl>

<FormControl sx={{ minWidth: 120 }}>
<InputLabel>No later than</InputLabel>
<Select
value={noLaterThan}
label="No later than"
onChange={(e) => setNoLaterThan(e.target.value)}
>
{hours.map((hour, index) => (
<MenuItem key={hour} value={index}>
{hour}
</MenuItem>
))}
</Select>
</FormControl>
</Box>

{/* Toggle for Weekends */}
<Box sx={{ display: 'flex', justifyContent: 'center', marginBottom: 2 }}>
<FormControlLabel
control={
<Switch
checked={includeWeekends}
onChange={(e) => setIncludeWeekends(e.target.checked)}
color="primary"
/>
}
label="Include Weekends"
/>
</Box>

{/* Time Grid */}
<Box
sx={{
display: 'grid',
gridTemplateColumns: `repeat(${includeWeekends ? weekdays.length + weekendDays.length + 1 : weekdays.length + 1}, 1fr)`,
gap: 1,
}}
>
<Box /> {/* Empty cell for alignment */}
{weekdays.map((day) => (
<Typography key={day} variant="subtitle1" align="center">
{day}
</Typography>
))}
{includeWeekends &&
weekendDays.map((day) => (
<Typography key={day} variant="subtitle1" align="center">
{day}
</Typography>
))}
{filteredHours.map((hour) => (
<React.Fragment key={hour}>
<Typography variant="subtitle2" align="center" sx={{ whiteSpace: 'nowrap' }}>
{hour}
</Typography>
{weekdays.map((day) => {
const slot = `${day}-${hour}`;
const isSelected = selectedTimes.includes(slot);

return (
<Paper
key={slot}
onClick={() => handleSlotClick(day, hour)}
sx={{
width: '100%',
height: 30,
backgroundColor: isSelected ? theme.palette.primary.main : 'white',
cursor: 'pointer',
border: '0.5px solid grey',
}}
/>
);
})}
{includeWeekends &&
weekendDays.map((day) => {
const slot = `${day}-${hour}`;
const isSelected = selectedTimes.includes(slot);

return (
<Paper
key={slot}
onClick={() => handleSlotClick(day, hour)}
sx={{
width: '100%',
height: 30,
backgroundColor: isSelected ? theme.palette.primary.main : 'white',
cursor: 'pointer',
border: '0.5px solid grey',
}}
/>
);
})}
</React.Fragment>
))}
</Box>
</Box>
);
};

export default React.memo(TimePreferencesGrid);
29 changes: 29 additions & 0 deletions src/components/Profile/TimePreferencesPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useState } from 'react';

import { Box, Typography, Button } from '@mui/material';

import TimePreferencesGrid from './TimePreferencesGrid';

export default function TimePreferencesPage() {
const [selectedTimes, setSelectedTimes] = useState([]);

const handleSavePreferences = () => {
console.log('Selected Times:', selectedTimes);
};

return (
<Box sx={{ maxWidth: 800, margin: 'auto', padding: 3, alignItems: 'center' }}>
<Typography variant="h4" align="center" gutterBottom>
Time Preferences
</Typography>

<TimePreferencesGrid selectedTimes={selectedTimes} setSelectedTimes={setSelectedTimes} />

<Box sx={{ display: 'flex', justifyContent: 'center', marginTop: 2 }}>
<Button variant="contained" onClick={handleSavePreferences}>
Save Preferences
</Button>
</Box>
</Box>
);
}
Loading