From fb641e8fd40989a5ab1feffc155c48239b2ffc06 Mon Sep 17 00:00:00 2001 From: tnagorra Date: Wed, 16 Oct 2024 10:29:25 +0545 Subject: [PATCH] Add icon support on group titles - Add clock on daily standup - Use human friendly date format on monthly calendar - Better UX for the availability dialog - Show disabled options instead of no option - Only show availability of un-available users --- src/components/Clock/index.tsx | 52 ++++++++++++++++++ src/components/MonthlyCalendar/index.tsx | 15 ++++-- .../MonthlyCalendar/styles.module.css | 4 ++ .../DailyJournal/AvailabilityDialog/index.tsx | 54 +++++++++---------- src/views/DailyJournal/DayView/index.tsx | 39 ++++++++++++++ .../DailyJournal/DayView/styles.module.css | 8 +++ src/views/DailyJournal/index.tsx | 3 +- .../GeneralEvent/styles.module.css | 2 +- .../DailyStandup/DeadlineSection/index.tsx | 25 ++------- src/views/DailyStandup/StartSection/index.tsx | 49 ++++++----------- src/views/DailyStandup/index.tsx | 8 +-- 11 files changed, 164 insertions(+), 95 deletions(-) create mode 100644 src/components/Clock/index.tsx diff --git a/src/components/Clock/index.tsx b/src/components/Clock/index.tsx new file mode 100644 index 0000000..3646d4c --- /dev/null +++ b/src/components/Clock/index.tsx @@ -0,0 +1,52 @@ +import { + useEffect, + useState, +} from 'react'; + +const dateTimeFormatter = new Intl.DateTimeFormat( + [], + { + year: 'numeric', + month: 'short', + day: 'numeric', + weekday: 'short', + hour: 'numeric', + minute: 'numeric', + // second: 'numeric', + hour12: true, + }, +); + +function formatTime(date: Date) { + return dateTimeFormatter.format(date); +} + +function Clock() { + const [dateStr, setDateStr] = useState(() => { + const date = new Date(); + return formatTime(date); + }); + useEffect( + () => { + const timeout = window.setInterval( + () => { + const date = new Date(); + const dateAsString = formatTime(date); + setDateStr(dateAsString); + }, + 500, + ); + return () => { + window.clearInterval(timeout); + }; + }, + [], + ); + return ( +
+ {dateStr} +
+ ); +} + +export default Clock; diff --git a/src/components/MonthlyCalendar/index.tsx b/src/components/MonthlyCalendar/index.tsx index 1bef486..ce56274 100644 --- a/src/components/MonthlyCalendar/index.tsx +++ b/src/components/MonthlyCalendar/index.tsx @@ -19,6 +19,14 @@ import DateContext from '#contexts/date'; import styles from './styles.module.css'; +const dateFormatter = new Intl.DateTimeFormat( + [], + { + year: 'numeric', + month: 'short', + }, +); + const weekDaysName = [ 'Su', 'Mo', @@ -129,6 +137,8 @@ function MonthlyCalendar(props: Props) { return days; }, [year, month]); + const formattedDate = dateFormatter.format(new Date(year, month, 1)); + return (
@@ -150,10 +160,9 @@ function MonthlyCalendar(props: Props) { > +
- {year} - / - {String(month + 1).padStart(2, '0')} + {formattedDate}
diff --git a/src/components/MonthlyCalendar/styles.module.css b/src/components/MonthlyCalendar/styles.module.css index e30eefe..1ee0139 100644 --- a/src/components/MonthlyCalendar/styles.module.css +++ b/src/components/MonthlyCalendar/styles.module.css @@ -8,6 +8,10 @@ gap: var(--spacing-sm); align-items: baseline; font-size: var(--font-size-sm); + + .spacer { + flex-grow: 1; + } } .monthly-calendar { diff --git a/src/views/DailyJournal/AvailabilityDialog/index.tsx b/src/views/DailyJournal/AvailabilityDialog/index.tsx index 60413d6..c464464 100644 --- a/src/views/DailyJournal/AvailabilityDialog/index.tsx +++ b/src/views/DailyJournal/AvailabilityDialog/index.tsx @@ -188,7 +188,8 @@ function AvailabilityDialog(props: Props) { return key === 'FIRST_HALF'; } if (dialogState.wfhType === 'FULL') { - return false; + // NOTE: So that we can see all options + return true; } return true; }, @@ -204,7 +205,8 @@ function AvailabilityDialog(props: Props) { return key === 'FIRST_HALF'; } if (dialogState.leaveType === 'FULL') { - return false; + // NOTE: So that we can see all options + return true; } return true; }, @@ -221,32 +223,28 @@ function AvailabilityDialog(props: Props) { contentClassName={styles.modalContent} className={styles.availabilityDialog} > - {dialogState.wfhType !== 'FULL' && ( - - )} - {dialogState.leaveType !== 'FULL' && ( - - )} + +
- {!isTruthyString(dateFromParams) && ( + {selectedDate !== fullDate && ( (() => { const deadlines = projects?.flatMap( (project) => project.deadlines.map((deadline) => ({ @@ -121,7 +102,7 @@ function DeadlineSection(props: Props) { variant="split" primaryPreText="Welcome to" primaryHeading="Daily Standup" - primaryDescription={formattedDate} + primaryDescription={} secondaryHeading="Upcoming Events" secondaryContent={upcomingEvents.map( (generalEvent, index) => ( diff --git a/src/views/DailyStandup/StartSection/index.tsx b/src/views/DailyStandup/StartSection/index.tsx index d9f872e..f7f4801 100644 --- a/src/views/DailyStandup/StartSection/index.tsx +++ b/src/views/DailyStandup/StartSection/index.tsx @@ -8,6 +8,7 @@ import { } from 'urql'; import AvailabilityIndicator from '#components/AvailabilityIndicator'; +import Clock from '#components/Clock'; import DisplayPicture from '#components/DisplayPicture'; import { type JournalLeaveTypeEnum, @@ -38,16 +39,6 @@ function getUnavailability( return sum; } -const dateFormatter = new Intl.DateTimeFormat( - [], - { - year: 'numeric', - month: 'short', - day: 'numeric', - weekday: 'short', - }, -); - const USERS_AVAILABILITY = gql` query UsersAvailability { private { @@ -64,17 +55,7 @@ const USERS_AVAILABILITY = gql` } `; -interface Props { - date: string; -} - -function StartSection(props: Props) { - const { - date, - } = props; - - const formattedDate = dateFormatter.format(new Date(date)); - +function StartSection() { const [usersAvailability] = useQuery< UsersAvailabilityQuery, UsersAvailabilityQueryVariables @@ -83,16 +64,18 @@ function StartSection(props: Props) { }); // FIXME: need to check how to sort these information - const sortedUsers = [...(usersAvailability.data?.private.users.items ?? [])].sort( - (foo, bar) => compareNumber( - getUnavailability(foo.leaveToday, foo.workFromHomeToday), - getUnavailability(bar.leaveToday, bar.workFromHomeToday), - -1, - ) || compareString( - foo.displayName, - bar.displayName, - ), - ); + const sortedUsers = usersAvailability.data?.private.users.items + .filter((item) => item.leaveToday || item.workFromHomeToday) + .sort( + (foo, bar) => compareNumber( + getUnavailability(foo.leaveToday, foo.workFromHomeToday), + getUnavailability(bar.leaveToday, bar.workFromHomeToday), + -1, + ) || compareString( + foo.displayName, + bar.displayName, + ), + ); return ( } + secondaryHeading="Availability" secondaryContent={sortedUsers?.map((user) => (
{mapId === 'start' && ( - + )} {mapId === 'deadlines' && ( - + )} {mapId !== 'start' && mapId !== 'end' && mapId !== 'deadlines' && (