Skip to content

Commit

Permalink
Move service calls into contexts and add refresh token impl (#20)
Browse files Browse the repository at this point in the history
* Move service calls into contexts and add refresh token impl

* Fill missing deps for useEffects
  • Loading branch information
domhhv authored Feb 2, 2024
1 parent 0ca4df0 commit cafa360
Show file tree
Hide file tree
Showing 16 changed files with 415 additions and 263 deletions.
37 changes: 9 additions & 28 deletions src/components/calendar/CalendarCell.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import {
CalendarEvent,
useCalendarEvents,
useSnackbar,
useUser,
} from '@context';
import { CalendarEvent, useCalendarEvents } from '@context';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
import FmdBadIcon from '@mui/icons-material/FmdBad';
import FmdGoodIcon from '@mui/icons-material/FmdGood';
import { ChipDelete, CircularProgress, Typography } from '@mui/joy';
import { calendarService } from '@services';
import React from 'react';

import {
Expand Down Expand Up @@ -39,14 +33,13 @@ const CalendarCell = ({
onClick,
rangeStatus,
}: CalendarCellProps) => {
const { user } = useUser();
const calendarEventsContext = useCalendarEvents();
const {
removeCalendarEvent,
fetchingCalendarEvents,
calendarEventIdBeingDeleted,
} = useCalendarEvents();
const [active, setActive] = React.useState(false);
const [current, setCurrent] = React.useState(false);
const [eventIdBeingDeleted, setEventIdBeingDeleted] = React.useState<
number | null
>(null);
const { showSnackbar } = useSnackbar();

React.useEffect(() => {
const today = new Date();
Expand Down Expand Up @@ -79,19 +72,7 @@ const CalendarCell = ({
clickEvent: React.MouseEvent<HTMLButtonElement>
) => {
clickEvent.stopPropagation();
setEventIdBeingDeleted(calendarEventId);

try {
await calendarService.destroyCalendarEvent(calendarEventId, user);
calendarEventsContext.removeCalendarEvent(calendarEventId);
showSnackbar('Your habit entry has been deleted from the calendar.', {
dismissible: true,
});
} catch (error) {
console.error(error);
} finally {
setEventIdBeingDeleted(null);
}
removeCalendarEvent(calendarEventId);
};

return (
Expand All @@ -101,7 +82,7 @@ const CalendarCell = ({
data-next-month={rangeStatus === 'above-range'}
data-current={current}
onClick={handleClick}
disabled={calendarEventsContext.fetchingCalendarEvents}
disabled={fetchingCalendarEvents}
>
<StyledCalendarDayCellButtonHeader>
<Typography level="body-sm" fontWeight={current ? 900 : 400}>
Expand All @@ -117,7 +98,7 @@ const CalendarCell = ({
{events.map((event) => {
const Icon = event.habit.trait === 'good' ? FmdGoodIcon : FmdBadIcon;

const isBeingDeleted = eventIdBeingDeleted === event.id;
const isBeingDeleted = calendarEventIdBeingDeleted === event.id;

const endDecorator = isBeingDeleted ? (
<CircularProgress size="sm" />
Expand Down
2 changes: 1 addition & 1 deletion src/components/calendar/CalendarGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const CalendarGrid = ({ state }: CalendarGridProps) => {
setDayModalDialogOpen(false);
};

const calendarEventsByDate = calendarEvents?.reduce(
const calendarEventsByDate = Object.values(calendarEvents).reduce(
(acc, event) => {
const date = new Date(event.date);
const year = date.getFullYear();
Expand Down
50 changes: 16 additions & 34 deletions src/components/calendar/DayHabitModalDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCalendarEvents, useHabits, useSnackbar, useUser } from '@context';
import { useCalendarEvents, useHabits } from '@context';
import {
Box,
Button,
Expand All @@ -14,7 +14,6 @@ import {
FormLabel,
FormHelperText,
} from '@mui/joy';
import { calendarService } from '@services';
import { format } from 'date-fns';
import React, { FormEventHandler } from 'react';

Expand All @@ -29,14 +28,11 @@ const DayHabitModalDialog = ({
onClose,
date,
}: DayHabitModalDialogProps) => {
const { user } = useUser();
const { habits } = useHabits();
const calendarEventsContext = useCalendarEvents();
const [submitting, setSubmitting] = React.useState(false);
const { addCalendarEvent, addingCalendarEvent } = useCalendarEvents();
const [selectedBadHabit, setSelectedBadHabit] = React.useState<number | null>(
null
);
const { showSnackbar } = useSnackbar();

if (!date || !open) {
return null;
Expand All @@ -45,35 +41,21 @@ const DayHabitModalDialog = ({
const handleSubmit: FormEventHandler<HTMLFormElement> = async (event) => {
event.preventDefault();

if (!selectedBadHabit) {
return null;
}
const calendarEvent = {
date: date.toISOString(),
habitId: selectedBadHabit as number,
};
await addCalendarEvent(calendarEvent);

setSubmitting(true);
try {
const newCalendarEvent = await calendarService.createCalendarEvent(
date,
selectedBadHabit as number,
user
);
calendarEventsContext.addCalendarEvent(newCalendarEvent);
showSnackbar('Your habit entry has been added to the calendar!', {
color: 'success',
dismissible: true,
dismissText: 'Done',
});
} catch (error) {
console.error(error);
} finally {
setSubmitting(false);
}
onClose();
};

const handleSelect = (_: null, newValue: string) => {
setSelectedBadHabit(Number(newValue));
};

const hasHabits = Object.keys(habits).length > 0;

return (
<Modal open={open} onClose={onClose}>
<ModalDialog sx={{ width: 380 }}>
Expand All @@ -91,26 +73,26 @@ const DayHabitModalDialog = ({
required
color={'neutral'}
placeholder="Select Habit"
value={habits.length ? selectedBadHabit : 0}
value={hasHabits ? selectedBadHabit : 0}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
onChange={handleSelect}
disabled={submitting}
disabled={addingCalendarEvent}
id="habit-select"
>
{!habits.length && (
{!hasHabits && (
<Option value={0} label="No habits found" disabled>
No habits found
</Option>
)}
{habits.map((habit) => (
{Object.values(habits).map((habit) => (
<Option key={habit.id} value={habit.id} label={habit.name}>
{habit.name}
<Typography level="body-xs">{habit.trait}</Typography>
</Option>
))}
</Select>
{!habits.length && (
{!hasHabits && (
<FormHelperText id="select-field-demo-helper">
Add a habit or some first
</FormHelperText>
Expand All @@ -119,8 +101,8 @@ const DayHabitModalDialog = ({
<Box mt={1}>
<Button
fullWidth
loading={submitting}
disabled={!habits.length}
loading={addingCalendarEvent}
disabled={!hasHabits}
type="submit"
>
Submit
Expand Down
22 changes: 8 additions & 14 deletions src/components/habit/add-habit/AddHabitDialogButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
Option,
Select,
} from '@mui/joy';
import { habitService } from '@services';
import React, { FormEventHandler } from 'react';

type AddHabitDialogButtonProps = {
Expand All @@ -31,8 +30,7 @@ const AddHabitDialogButton = ({
const [habitName, setHabitName] = React.useState('');
const [habitDescription, setHabitDescription] = React.useState('');
const [habitTrait, setHabitTrait] = React.useState<'good' | 'bad' | ''>('');
const [addingHabit, setAddingHabit] = React.useState(false);
const habitsContext = useHabits();
const { addingHabit, addHabit } = useHabits();
const { showSnackbar } = useSnackbar();

const handleDialogOpen = () => {
Expand All @@ -48,16 +46,13 @@ const AddHabitDialogButton = ({

const handleAdd: FormEventHandler<HTMLFormElement> = async (event) => {
event.preventDefault();
setAddingHabit(true);

try {
const newHabit = await habitService.createHabit(
habitName,
habitDescription,
habitTrait as 'good' | 'bad',
user
);
habitsContext.addHabit(newHabit);
const habit = {
name: habitName,
description: habitDescription,
trait: habitTrait as 'good' | 'bad',
};
addHabit(habit);
showSnackbar('Your habit has been added!', {
color: 'success',
dismissible: true,
Expand All @@ -71,7 +66,6 @@ const AddHabitDialogButton = ({
});
console.error(error);
} finally {
setAddingHabit(false);
setOpen(false);
}
};
Expand Down Expand Up @@ -99,7 +93,7 @@ const AddHabitDialogButton = ({
variant="soft"
startDecorator={<AddRounded />}
onClick={handleDialogOpen}
disabled={disabled || !user.token}
disabled={disabled || !user.accessToken}
>
Add habit
</Button>
Expand Down
49 changes: 11 additions & 38 deletions src/components/habit/edit-habit/EditHabitDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { FloatingLabelInput, FloatingLabelTextarea } from '@components';
import {
Habit,
useCalendarEvents,
useHabits,
useSnackbar,
useUser,
} from '@context';
import { Habit, useCalendarEvents, useHabits } from '@context';
import {
Button,
DialogContent,
Expand All @@ -16,7 +10,6 @@ import {
Option,
Select,
} from '@mui/joy';
import { habitService } from '@services';
import React from 'react';

import { StyledForm } from './styled';
Expand All @@ -32,15 +25,13 @@ const EditHabitDialog = ({
habit,
onClose,
}: EditHabitDialogProps) => {
const { user } = useUser();
const [isOpen, setIsOpen] = React.useState(false);
const [name, setName] = React.useState('');
const [description, setDescription] = React.useState('');
const [trait, setTrait] = React.useState<'good' | 'bad' | ''>('');
const [isUpdating, setIsUpdating] = React.useState(false);
const habitsContext = useHabits();
const { updateHabitInsideCalendarEvents } = useCalendarEvents();
const { showSnackbar } = useSnackbar();

React.useEffect(() => {
setIsOpen(open);
Expand Down Expand Up @@ -80,34 +71,16 @@ const EditHabitDialog = ({
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setIsUpdating(true);

try {
const updatedHabit = await habitService.updateHabit(
habit.id,
{
name,
description,
trait: trait as 'good' | 'bad',
},
user
);
habitsContext.updateHabit(updatedHabit);
updateHabitInsideCalendarEvents(updatedHabit);
showSnackbar('Your habit has been updated!', {
color: 'success',
dismissible: true,
dismissText: 'Done',
});
} catch (error) {
showSnackbar('Something went wrong', {
color: 'danger',
dismissible: true,
});
console.error(error);
} finally {
setIsUpdating(false);
handleClose();
}
const newHabit = {
id: habit.id,
name,
description,
trait: trait as 'good' | 'bad',
};
await habitsContext.updateHabit(newHabit);
updateHabitInsideCalendarEvents(newHabit);
setIsUpdating(false);
handleClose();
};

return (
Expand Down
23 changes: 6 additions & 17 deletions src/components/habit/view-habit/HabitItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Habit, useHabits, useSnackbar, useUser } from '@context';
import { Habit, useCalendarEvents, useHabits } from '@context';
import { DeleteForever } from '@mui/icons-material';
import ModeRoundedIcon from '@mui/icons-material/ModeRounded';
import {
Expand All @@ -9,7 +9,6 @@ import {
Tooltip,
Typography,
} from '@mui/joy';
import { habitService } from '@services';
import React from 'react';

import {
Expand All @@ -25,25 +24,15 @@ type HabitItemProps = {
};

const HabitItem = ({ habit, onEdit }: HabitItemProps) => {
const { user } = useUser();
const [isBeingDeleted, setIsBeingDeleted] = React.useState(false);
const habitsContext = useHabits();
const { showSnackbar } = useSnackbar();
const { removeHabit } = useHabits();
const { removeCalendarEventsByHabitId } = useCalendarEvents();

const handleDeleteHabit = async () => {
setIsBeingDeleted(true);

try {
await habitService.destroyHabit(habit.id, user);
habitsContext.removeHabit(habit.id);
showSnackbar('Your habit has been deleted!', {
dismissible: true,
});
} catch (error) {
console.error(error);
} finally {
setIsBeingDeleted(false);
}
await removeHabit(habit.id);
removeCalendarEventsByHabitId(habit.id);
setIsBeingDeleted(false);
};

return (
Expand Down
Loading

0 comments on commit cafa360

Please sign in to comment.