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

79 user dashboard 2 #80

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
84f54c8
install react-native-calendars
cshimm Feb 4, 2025
ee64f7f
basic month & week view set up
cshimm Feb 4, 2025
b104a6d
added dummy Shift Data
cshimm Feb 4, 2025
078d7ad
marked dates logic
cshimm Feb 4, 2025
be5fc52
added day view item
cshimm Feb 6, 2025
1097d1c
adjust dummy data
cshimm Feb 6, 2025
d9a8a4f
added agenda list
cshimm Feb 6, 2025
2259020
Merge branch 'main' into 79-user-dashboard-2
cshimm Feb 6, 2025
93b51f0
change agenda items initialization code to only run once
cshimm Feb 6, 2025
718b867
added user dashboard link to home page
cshimm Feb 6, 2025
2c0dcf3
update DayViewItem.tsx
cshimm Feb 6, 2025
6b607c6
code reformatting
cshimm Feb 6, 2025
c5106a2
code cleanup
cshimm Feb 6, 2025
2c2a25e
add time conversion functions
cshimm Feb 6, 2025
3a7b7fe
add time conversion functions
cshimm Feb 6, 2025
b38c564
Merge remote-tracking branch 'origin/79-user-dashboard-2' into 79-use…
cshimm Feb 6, 2025
fdf7176
revert coworkerslist changes
cshimm Feb 6, 2025
97d9f9f
remove unused useEffects
cshimm Feb 6, 2025
d8a48be
options arrays added, minor fixes
cshimm Feb 7, 2025
27d9340
added more data
cshimm Feb 7, 2025
30744ea
added more data
cshimm Feb 7, 2025
beb7c99
Merge remote-tracking branch 'origin/79-user-dashboard-2' into 79-use…
cshimm Feb 7, 2025
b8423c3
scroll to current date, switch week and month placement
cshimm Feb 8, 2025
1234334
update dummy data
cshimm Feb 9, 2025
b932735
on render items of current week in week view
cshimm Feb 9, 2025
e99dff6
update DayViewItem.tsx
cshimm Feb 9, 2025
db5bb45
convert to using themed components
cshimm Feb 9, 2025
51532f5
added timeframes enum
cshimm Feb 9, 2025
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
3 changes: 3 additions & 0 deletions app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export default function HomeScreen(): ReactElement {

<Link href="/(tabs)"
style={linkStyle}>Go to main app features after login</Link>
<Link
href="/user-dashboard"
style={linkStyle}>User Dashboard Page</Link>
<Link
href="/(auth)/forgot-password"
style={linkStyle}>Forgot Password Page</Link>
Expand Down
227 changes: 177 additions & 50 deletions app/user-dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,201 @@
import React, {useEffect} from 'react';
import { Image, StyleSheet, View, Text } from 'react-native';

import ParallaxScrollView from '@/components/ParallaxScrollView';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {StyleSheet, SectionList} from 'react-native';
import { supabase } from '@/supabaseClient';
import {OptionToggle} from "@/components/dashboard/OptionToggle";
import {AgendaList, Calendar, CalendarProvider, WeekCalendar} from "react-native-calendars";
import {shiftData, ShiftData} from "@/data/dummyShiftData";
import {MarkedDates} from "react-native-calendars/src/types";
import {DayViewItem} from "@/components/DayViewItem";
import {ThemedView} from "@/components/ThemedView";
import {ThemedText} from "@/components/ThemedText";

interface DateProps {
dateString: string,
day: number,
month: number,
timestamp: number,
year: number,
}
interface AgendaListProps {
title: string,
data: any[]
}
enum Timeframes {
Week = "Week",
Month = "Month"
}
const getMarkedDates = (shifts: ShiftData[], selectedDate: string) => {
let marked: MarkedDates = {};
shifts.forEach(({ date, id }) => {
if (!marked[date]) {
marked[date] = {
marked: true,
dots: [{
key: `${date}-${id}`,
color: 'black'
}]
};
} else {
marked[date].dots?.push({
key: `${date}-${id}`,
color: 'black'
})
}
});

marked[selectedDate] = {
...(marked[selectedDate] || {}),
selected: true,
dots: [...(marked[selectedDate]?.dots || [])]
}

return marked;
};
export default function UserDashboard() {
const [selectedTimeframe, setSelectedTimeframe] = React.useState<string | undefined>();
const [selectedApprovalStatus, setSelectedApprovalStatus] = React.useState<string | undefined>();
const today = new Intl.DateTimeFormat('en-CA').format(new Date());
const timeframeOptions = [Timeframes.Month, Timeframes.Week];
const approvalStatusOptions = ['Pending', 'Approved', 'Denied'];
const [selectedTimeframe, setSelectedTimeframe] = useState<Timeframes | undefined>(timeframeOptions[0]);
const [selectedApprovalStatus, setSelectedApprovalStatus] = useState<string | undefined>(approvalStatusOptions[0]);
const [selectedDate, setSelectedDate] = useState<string>(today);
const [agendaListItems, setAgendaListItems] = useState<any[]>([]);
const [markedDates, setMarkedDates] = useState<MarkedDates>();

useEffect(() => {
console.log(selectedApprovalStatus);
}, [selectedApprovalStatus]);
initializeAgendaItems();
}, []);

useEffect(() => {
setMarkedDates(getMarkedDates(shiftData, selectedDate))
}, [selectedDate]);

useEffect(() => {
console.log(selectedTimeframe);
if (selectedTimeframe === Timeframes.Week) {
setSelectedDate(today);
}
}, [selectedTimeframe]);
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
headerImage={
<Image
source={require('@/assets/images/partial-react-logo.png')}
style={styles.reactLogo}
/>
}>
const initializeAgendaItems = () => {
const items: AgendaListProps[] = [];
shiftData.forEach(shift => {
const existing = items.findIndex(item => item.title === shift.date);
const shiftItem = {
startTime: shift.startTime,
endTime: shift.endTime,
role: shift.role,
roomNumber: shift.roomNumber,
building: shift.building,
title: "Shift"
}
if (existing === -1) {
items.push({
title: shift.date,
data: [...[shiftItem]],
})
} else {
items[existing].data.push(shiftItem);
}
})
setAgendaListItems(items);
}

const isDateInCurrentWeek = (dateStr: string): boolean => {
const inputDate = new Date(dateStr);
const today = new Date();

const startOfWeek = new Date(today);
startOfWeek.setDate(today.getDate() - today.getDay());
startOfWeek.setHours(0, 0, 0, 0);

const endOfWeek = new Date(startOfWeek);
endOfWeek.setDate(startOfWeek.getDate() + 6);
endOfWeek.setHours(23, 59, 59, 999);

return inputDate >= startOfWeek && inputDate <= endOfWeek;
}
const handleDatePress = (date: DateProps) => {
setSelectedDate(date.dateString);
}

const renderItem = useCallback(({item}: any) => {
return <DayViewItem item={item}/>
}, []);

const agendaRef = useRef<SectionList>(null);
const scrollToEvent = (dateIndex: number, itemIndex: number) => {
if (agendaRef.current) {
agendaRef.current.scrollToLocation({
sectionIndex: dateIndex,
itemIndex: itemIndex,
animated: true,
});
}
};

return (
<ThemedView style={{flex: 1}}>
<CalendarProvider
date={selectedDate}
onDateChanged={setSelectedDate}
showTodayButton={false}
>
{/* Schedule Title*/}
<View style={styles.scheduleContainer}>
<Text style={styles.scheduleTitle}>Schedule</Text>
<ThemedView style={styles.scheduleContainer}>
<ThemedText style={styles.scheduleTitle}>Schedule</ThemedText>
<OptionToggle
options={['Week', 'Month']}
options={timeframeOptions.map(tf => tf.toString())}
gap={8}
handleToggledOption={setSelectedTimeframe}
handleToggledOption={(value) => setSelectedTimeframe(value === Timeframes.Month.toString() ? Timeframes.Month : Timeframes.Week)}
/>
<OptionToggle
options={['Pending', 'Approved', 'Denied']}
options={approvalStatusOptions}
gap={4}
handleToggledOption={setSelectedApprovalStatus}
/>
</View>

{/* Placeholder Box */}
<View style={styles.placeholderBox}>
<Text style={styles.placeholderText}>
Calendar Components Placeholder Box
</Text>
</View>
</ParallaxScrollView>
</ThemedView>
{
selectedTimeframe === Timeframes.Month ?
(
<Calendar
enableSwipeMonths={true}
markingType={"multi-dot"}
onDayPress={(day: DateProps) => handleDatePress(day)}
markedDates={markedDates}
/>
)
: (
<WeekCalendar
markingType={'multi-dot'}
enableSwipeMonths={false}
onDayPress={(day: DateProps) => handleDatePress(day)}
markedDates={markedDates}
current={selectedDate}
initialDate={today}
/>
)
}
<AgendaList
ref={agendaRef}
sections={selectedTimeframe === Timeframes.Month ?
agendaListItems :
agendaListItems.filter(item => {
return isDateInCurrentWeek(item.title);
})}
avoidDateUpdates={selectedTimeframe === Timeframes.Week}
renderItem={renderItem}
onLayout={() => scrollToEvent(0,0)}
contentContainerStyle={{paddingBottom: 50}}
infiniteListProps={{
itemHeight: 115,
titleHeight: 45,
visibleIndicesChangedDebounce: 250,
}}
/>
</CalendarProvider>
</ThemedView>
);
}

const styles = StyleSheet.create({
reactLogo: {
height: 178,
width: 290,
bottom: 0,
left: 0,
position: 'absolute',
},
scheduleContainer: {
margin: 16,
alignItems: 'center',
Expand All @@ -67,15 +205,4 @@ const styles = StyleSheet.create({
fontWeight: 'bold',
marginBottom: 16,
},
placeholderBox: {
marginTop: 16,
padding: 16,
backgroundColor: '#f0f0f0',
borderRadius: 8,
alignItems: 'center',
},
placeholderText: {
fontSize: 16,
color: 'black',
},
});
38 changes: 38 additions & 0 deletions components/DayViewItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {Text, View} from "react-native";
import React from "react";
import {ThemedText} from "@/components/ThemedText";
import {ThemedView} from "@/components/ThemedView";

interface DayViewItemProps {
item: any,
}

export const DayViewItem = ({item}: DayViewItemProps) => {
const start = Number(item.startTime.split(':')[0]);
const end = Number(item.endTime.split(':')[0]);
const numHoursScheduled = end - start;
const setAMOrPM = (time: number) => time >= 12 ? "pm" : 'am';
const to12Hours = (time: number) => time > 12 ? time - 12 : time;
return (
<ThemedView>
<ThemedView lightColor={'#CFD8DC'} darkColor={'#CFD8DC'} style={{
marginBottom: 10,
width: '70%',
padding: 10,
paddingLeft: 20,
borderRadius: 20
}}>
<ThemedText style={{fontSize: 16}}>{item.role}</ThemedText>
<ThemedText style={{flexDirection: 'row', justifyContent: 'flex-start', fontSize: 12, color: '#3e3e3e'}}>
<ThemedText>{item.building}: </ThemedText>
<ThemedText>{item.roomNumber}</ThemedText>
</ThemedText>
<ThemedText style={{flexDirection: 'row', justifyContent: 'flex-start', fontSize: 16, marginVertical: 4}}>
<ThemedText style={{fontWeight: 'bold'}}>{numHoursScheduled} HR</ThemedText>
<ThemedText> | {`${to12Hours(start)}${setAMOrPM(start)} - ${to12Hours(end)}${setAMOrPM(end)}`}</ThemedText>
<ThemedText>{item.duration}</ThemedText>
</ThemedText>
</ThemedView>
</ThemedView>
)
}
Loading