Skip to content

Commit

Permalink
Add icon support on group titles
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
tnagorra committed Oct 16, 2024
1 parent b5394cf commit 170a5cd
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 32 deletions.
15 changes: 12 additions & 3 deletions src/components/MonthlyCalendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -129,6 +137,8 @@ function MonthlyCalendar(props: Props) {
return days;
}, [year, month]);

const formattedDate = dateFormatter.format(new Date(year, month, 1));

return (
<div className={_cs(styles.calendarContainer, className)}>
<div className={styles.header}>
Expand All @@ -150,10 +160,9 @@ function MonthlyCalendar(props: Props) {
>
<RiArrowRightSLine />
</Button>
<div className={styles.spacer} />
<div>
{year}
/
{String(month + 1).padStart(2, '0')}
{formattedDate}
</div>
</div>
<div className={styles.monthlyCalendar}>
Expand Down
4 changes: 4 additions & 0 deletions src/components/MonthlyCalendar/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
gap: var(--spacing-sm);
align-items: baseline;
font-size: var(--font-size-sm);

.spacer {
flex-grow: 1;
}
}

.monthly-calendar {
Expand Down
54 changes: 26 additions & 28 deletions src/views/DailyJournal/AvailabilityDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},
Expand All @@ -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;
},
Expand All @@ -221,32 +223,28 @@ function AvailabilityDialog(props: Props) {
contentClassName={styles.modalContent}
className={styles.availabilityDialog}
>
{dialogState.wfhType !== 'FULL' && (
<RadioInput
name="leaveType"
label="Leave"
options={availableLeaveTypeOptions}
keySelector={leaveTypeKeySelector}
labelSelector={leaveTypeLabelSelector}
onChange={setFieldValue}
value={dialogState.leaveType}
disabled={disabled}
clearable
/>
)}
{dialogState.leaveType !== 'FULL' && (
<RadioInput
name="wfhType"
label="Work from home"
options={availableWfhTypeOptions}
keySelector={wfhTypeKeySelector}
labelSelector={wfhTypeLabelSelector}
onChange={setFieldValue}
value={dialogState.wfhType}
disabled={disabled}
clearable
/>
)}
<RadioInput
name="leaveType"
label="Leave"
options={availableLeaveTypeOptions}
keySelector={leaveTypeKeySelector}
labelSelector={leaveTypeLabelSelector}
onChange={setFieldValue}
value={dialogState.leaveType}
disabled={disabled || dialogState.wfhType === 'FULL'}
clearable
/>
<RadioInput
name="wfhType"
label="Work from home"
options={availableWfhTypeOptions}
keySelector={wfhTypeKeySelector}
labelSelector={wfhTypeLabelSelector}
onChange={setFieldValue}
value={dialogState.wfhType}
disabled={disabled || dialogState.leaveType === 'FULL'}
clearable
/>
<div className={styles.actions}>
<Button
title="Cancel update availability"
Expand Down
39 changes: 39 additions & 0 deletions src/views/DailyJournal/DayView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,23 @@ function DayView(props: Props) {
return undefined;
}, [taskById]);

const getWorkItemIconFromAttr = useCallback((
item: WorkItem,
attr: DailyJournalAttribute,
) => {
if (isNotDefined(taskById)) {
return undefined;
}

const taskDetails = taskById[item.task];

if (attr.key === 'project') {
return taskDetails.contract.project.logo;
}

return undefined;
}, [taskById]);

const formattedDate = dateFormatter.format(new Date(selectedDate));
const formattedRelativeDate = useFormattedRelativeDate(selectedDate);

Expand Down Expand Up @@ -199,6 +216,10 @@ function DayView(props: Props) {
groupedItem.value,
groupedItem.attribute,
);
const currentIcon = getWorkItemIconFromAttr(
groupedItem.value,
groupedItem.attribute,
);

const Heading = `h${bound(groupedItem.level + 2, 2, 4)}` as unknown as ElementType;

Expand All @@ -208,6 +229,13 @@ function DayView(props: Props) {
className={styles.nestedHeading}
>
{indent && <Indent level={groupedItem.level} />}
{currentIcon && (
<img
className={styles.icon}
src={currentIcon.url}
alt={headingText}
/>
)}
{headingText}
</Heading>
);
Expand Down Expand Up @@ -236,6 +264,10 @@ function DayView(props: Props) {
groupedItem.value,
attribute,
);
const currentIcon = getWorkItemIconFromAttr(
groupedItem.value,
attribute,
);

if (i < (groupLevel - joinLevel)) {
return null;
Expand All @@ -246,6 +278,13 @@ function DayView(props: Props) {
{i > (groupLevel - joinLevel) && (
<div className={styles.separator} />
)}
{currentIcon && (
<img
className={styles.icon}
src={currentIcon.url}
alt={currentLabel}
/>
)}
<div>{currentLabel}</div>
</Fragment>
);
Expand Down
8 changes: 8 additions & 0 deletions src/views/DailyJournal/DayView/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@

&h2 {
margin-top: var(--spacing-md);

.icon {
height: 1em;
}
}
}

Expand All @@ -76,6 +80,10 @@
width: 0.5rem;
height: 0.5rem;
}

.icon {
height: 1em;
}
}

.work-item-container {
Expand Down
2 changes: 1 addition & 1 deletion src/views/DailyJournal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ export function Component() {
>
Add entry
</Button>
{!isTruthyString(dateFromParams) && (
{selectedDate !== fullDate && (
<Link
to="dailyJournal"
variant="quaternary"
Expand Down
50 changes: 50 additions & 0 deletions src/views/DailyStandup/StartSection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {
useEffect,
useState,
} from 'react';
import {
compareNumber,
compareString,
Expand Down Expand Up @@ -64,6 +68,52 @@ const USERS_AVAILABILITY = gql`
}
`;

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() {

Check failure on line 89 in src/views/DailyStandup/StartSection/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

'Clock' is declared but its value is never read.

Check warning on line 89 in src/views/DailyStandup/StartSection/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'Clock' is defined but never used
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 (
<div>
{dateStr}
</div>
);
}

interface Props {
date: string;
}
Expand Down

0 comments on commit 170a5cd

Please sign in to comment.