Skip to content

Commit

Permalink
feat(calendar): add basic viewing of occurrence notes (#134)
Browse files Browse the repository at this point in the history
* feat(calendar): add basic viewing of occurrence notes

* tweak variants and copies

* fix: tests
  • Loading branch information
domhhv authored Dec 25, 2024
1 parent 822c53b commit 2bada25
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/components/calendar/AddOccurrenceDialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe(AddOccurrenceDialog.name, () => {
<AddOccurrenceDialog {...props} />
</BrowserRouter>
);
expect(getByText('Add habit entries for 2021-01-01')).toBeInTheDocument();
expect(getByText('Add habit entry for 2021-01-01')).toBeInTheDocument();
});

it('should not render if date is null', () => {
Expand Down
11 changes: 8 additions & 3 deletions src/components/calendar/AddOccurrenceDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ const AddOccurrenceDialog = ({
>
<ModalContent>
<ModalHeader>
Add habit entries for {format(date, 'iii, LLL d, y')}
Add habit entry for {format(date, 'iii, LLL d, y')}
</ModalHeader>
<ModalBody>
<Select
disableSelectorIconRotation
variant="flat"
variant="faded"
selectedKeys={selectedHabitId}
label={
hasHabits
Expand Down Expand Up @@ -138,7 +138,12 @@ const AddOccurrenceDialog = ({
</SelectSection>
))}
</Select>
<Textarea onValueChange={setNote} value={note} placeholder="Note" />
<Textarea
onValueChange={setNote}
value={note}
placeholder="Note"
variant="faded"
/>
</ModalBody>
<ModalFooter>
<Button
Expand Down
3 changes: 3 additions & 0 deletions src/components/calendar/OccurrenceChip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ jest.mock('@hooks', () => ({

jest.mock('@stores', () => ({
useOccurrencesStore: jest.fn(),
useNotesStore: jest.fn().mockReturnValue({
notes: [],
}),
}));

describe(OccurrenceChip.name, () => {
Expand Down
58 changes: 54 additions & 4 deletions src/components/calendar/OccurrenceChip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import type { Occurrence } from '@models';
import { Badge, Button, Tooltip } from '@nextui-org/react';
import { Trash } from '@phosphor-icons/react';
import {
Badge,
Button,
Popover,
PopoverContent,
PopoverTrigger,
Tooltip,
} from '@nextui-org/react';
import { Note, Trash } from '@phosphor-icons/react';
import { useNotesStore } from '@stores';
import { getHabitIconUrl } from '@utils';
import React from 'react';

Expand All @@ -18,10 +26,18 @@ const OccurrenceChip = ({
onDelete,
colorOverride,
}: OccurrenceChipProps) => {
const [{ habit }] = occurrences;
const [occurrence] = occurrences;
const { habit } = occurrence;
const { notes } = useNotesStore();
const { name: habitName, iconPath, trait } = habit || {};
const { color: traitColor } = trait || {};
const iconUrl = getHabitIconUrl(iconPath);
const occurrenceNote = notes.find(
(note) => note.occurrenceId === occurrences[0].id
);
const [isOccurrenceTooltipOpen, setIsOccurrenceTooltipOpen] =
React.useState(false);
const [isNotePopoverOpen, setIsNotePopoverOpen] = React.useState(false);

const chipStyle = {
borderColor: colorOverride || traitColor,
Expand All @@ -30,6 +46,27 @@ const OccurrenceChip = ({
const tooltipContent = (
<div className="flex items-center justify-between gap-2">
{habitName}
{occurrenceNote && (
<Popover
isOpen={isNotePopoverOpen}
onOpenChange={(open) => setIsNotePopoverOpen(open)}
>
<PopoverTrigger>
<Button
color="primary"
variant="solid"
size="sm"
isIconOnly
className="h-6 w-6 min-w-0 rounded-lg"
>
<Note />
</Button>
</PopoverTrigger>
<PopoverContent>
<p className="text-tiny">{occurrenceNote.content}</p>
</PopoverContent>
</Popover>
)}
<Button
isIconOnly
variant="solid"
Expand All @@ -47,14 +84,19 @@ const OccurrenceChip = ({
const chip = (
<div
style={chipStyle}
className="mr-1 mt-1 min-w-0 rounded-full border-1 bg-slate-100 p-1.5 dark:bg-slate-800"
className="relative mr-1 mt-1 min-w-0 rounded-full border-1 bg-slate-100 p-1.5 dark:bg-slate-800"
role="habit-chip"
>
<img
src={iconUrl}
alt={`${habitName} icon`}
className="h-4 w-4 rounded"
/>
{occurrenceNote && (
<div className="absolute -right-2 -top-2 text-slate-400">
<Note size={16} weight="fill" />
</div>
)}
</div>
);

Expand All @@ -77,6 +119,14 @@ const OccurrenceChip = ({

return (
<Tooltip
isOpen={isOccurrenceTooltipOpen}
onOpenChange={(open) => {
if (isNotePopoverOpen && !open) {
return;
}

setIsOccurrenceTooltipOpen(open);
}}
isDisabled={!habitName}
content={tooltipContent}
radius="sm"
Expand Down
3 changes: 3 additions & 0 deletions src/components/habit/add-habit/AddHabitDialogButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,21 @@ const AddHabitDialogButton = () => {
onChange={handleNameChange}
label="Name"
placeholder="Enter habit name"
variant="faded"
/>
<Textarea
value={description}
onChange={handleDescriptionChange}
label="Description"
placeholder="Enter habit description (optional)"
variant="faded"
/>
<Select
required
label="Choose a trait"
selectedKeys={[traitId]}
data-testid="habit-select"
variant="faded"
>
{traits.map((trait) => (
<SelectItem
Expand Down
3 changes: 3 additions & 0 deletions src/components/habit/edit-habit/EditHabitDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,22 @@ const EditHabitDialog = ({
label="Name"
placeholder="Edit habit name"
isDisabled={isUpdating}
variant="faded"
/>
<Textarea
value={description}
onChange={handleDescriptionChange}
label="Description (optional)"
placeholder="Edit habit description"
isDisabled={isUpdating}
variant="faded"
/>
<Select
required
label="Trait"
selectedKeys={[traitId]}
data-testid="habit-select"
variant="faded"
>
{traits.map((trait) => (
<SelectItem
Expand Down
4 changes: 4 additions & 0 deletions src/components/habit/habits-page/HabitsPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ jest.mock('@stores', () => ({
useOccurrencesStore: jest.fn().mockReturnValue({
removeOccurrencesByHabitId: jest.fn(),
}),
useNotesStore: jest.fn().mockReturnValue({
addingNote: false,
addNote: jest.fn(),
}),
}));

jest.mock('@hooks', () => ({
Expand Down
12 changes: 11 additions & 1 deletion src/hooks/useFetchOnAuth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useTraitsStore, useHabitsStore, useOccurrencesStore } from '@stores';
import {
useTraitsStore,
useHabitsStore,
useOccurrencesStore,
useNotesStore,
} from '@stores';
import { useSupabaseClient } from '@supabase/auth-helpers-react';
import React from 'react';

Expand All @@ -7,6 +12,7 @@ const useFetchOnAuth = () => {
const { fetchTraits, clearTraits } = useTraitsStore();
const { fetchHabits, clearHabits } = useHabitsStore();
const { fetchOccurrences, clearOccurrences } = useOccurrencesStore();
const { fetchNotes, clearNotes } = useNotesStore();

React.useEffect(() => {
if (!supabase.auth) {
Expand All @@ -18,12 +24,14 @@ const useFetchOnAuth = () => {
clearTraits();
clearHabits();
clearOccurrences();
clearNotes();
}

if (['TOKEN_REFRESHED', 'SIGNED_IN'].includes(event)) {
void fetchTraits();
void fetchHabits();
void fetchOccurrences();
void fetchNotes();
}
});

Expand All @@ -35,9 +43,11 @@ const useFetchOnAuth = () => {
fetchTraits,
clearTraits,
fetchHabits,
fetchNotes,
clearHabits,
fetchOccurrences,
clearOccurrences,
clearNotes,
]);
};

Expand Down
2 changes: 1 addition & 1 deletion src/stores/occurrences.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const useOccurrencesStore = create<OccurrencesState>((set, get) => {
set((state) => ({
allOccurrences: [...state.allOccurrences, nextOccurrence],
}));
showSnackbar('Habit entry(s) are added to the calendar', {
showSnackbar('Habit entry added to the calendar', {
color: 'success',
dismissible: true,
dismissText: 'Done',
Expand Down

0 comments on commit 2bada25

Please sign in to comment.