Skip to content

Commit

Permalink
Merge pull request #104 from cabcookie:dayplan-improvements
Browse files Browse the repository at this point in the history
feat: set default date when adding a new day plan
  • Loading branch information
cabcookie authored Jun 4, 2024
2 parents 36ce2e5 + a9e6831 commit d59197b
Show file tree
Hide file tree
Showing 9 changed files with 397 additions and 69 deletions.
52 changes: 51 additions & 1 deletion api/useDayplans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ const mapDayPlan: (dayplan: DayPlanData) => DayPlan = ({
doneOn: doneOn ? new Date(doneOn) : undefined,
projectId: project?.id,
}))
.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()),
.sort((a, b) =>
a.done === b.done
? a.createdAt.getTime() - b.createdAt.getTime()
: (a.done ? 1 : 0) - (b.done ? 1 : 0)
),
projectTasks: projectTasks
.map(({ id, task, done, createdAt, projects }) => ({
id,
Expand Down Expand Up @@ -149,6 +153,13 @@ type CreateTodoFn = (props: {
projectId?: string;
}) => Promise<Schema["DayPlanTodo"]["type"] | undefined>;

type UpdateTodoFn = (
todo: string,
todoId: string
) => Promise<string | undefined>;

type DeleteTodoFn = (todoId: string) => Promise<string | undefined>;

type SwitchTodoDoneFn = (todoId: string, done: boolean) => Promise<void>;

const checkForLegacyTasks = async (setCount: (count: number) => void) => {
Expand Down Expand Up @@ -335,6 +346,43 @@ const useDayPlans = (context?: Context) => {
return data || undefined;
};

const updateTodo: UpdateTodoFn = async (todo, todoId) => {
const updated: DayPlan[] | undefined = dayPlans?.map((d) =>
!d.todos.some((t) => t.id === todoId)
? d
: {
...d,
todos: d.todos.map((t) => (t.id !== todoId ? t : { ...t, todo })),
}
);
if (updated) mutate(updated, false);
const { data, errors } = await client.models.DayPlanTodo.update({
id: todoId,
todo,
});
if (errors) handleApiErrors(errors, "Error updating todo");
if (updated) mutate(updated);
return data?.id;
};

const deleteTodo: DeleteTodoFn = async (todoId) => {
const updated: DayPlan[] | undefined = dayPlans?.map((d) =>
!d.todos.some((t) => t.id === todoId)
? d
: {
...d,
todos: d.todos.filter((t) => t.id !== todoId),
}
);
if (updated) mutate(updated, false);
const { data, errors } = await client.models.DayPlanTodo.delete({
id: todoId,
});
if (errors) handleApiErrors(errors, "Error deleting task from day plan.");
if (updated) mutate(updated);
return data?.id;
};

const switchTodoDone: SwitchTodoDoneFn = async (todoId, done) => {
const updated = dayPlans?.map(({ todos, ...rest }) => ({
...rest,
Expand All @@ -359,6 +407,8 @@ const useDayPlans = (context?: Context) => {
completeDayPlan,
undoDayplanCompletion,
createTodo,
updateTodo,
deleteTodo,
switchTodoDone,
migrateLegacyTasks,
countLegacyTasks,
Expand Down
13 changes: 5 additions & 8 deletions components/dayplan/dayplan-form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { addDaysToDate } from "@/helpers/functional";
import { cn } from "@/lib/utils";
import { zodResolver } from "@hookform/resolvers/zod";
import { format } from "date-fns";
import { addDays, format, getHours } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { FC } from "react";
import { useForm } from "react-hook-form";
Expand All @@ -18,7 +18,6 @@ import {
} from "../ui/form";
import { Input } from "../ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { useToast } from "../ui/use-toast";

const FormSchema = z.object({
goal: z
Expand All @@ -44,15 +43,13 @@ const DayPlanForm: FC<DayPlanFormProps> = ({
}) => {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: { goal: "" },
defaultValues: {
goal: "",
date: getHours(new Date()) < 12 ? new Date() : addDays(new Date(), 1),
},
});
const { toast } = useToast();

const handleSubmit = ({ date, goal }: z.infer<typeof FormSchema>) => {
toast({
title: "You created a new day plan.",
description: `Your goal for ${date.toLocaleDateString()} is "${goal}".`,
});
onSubmit(goal, date);
};

Expand Down
3 changes: 0 additions & 3 deletions components/dayplan/task-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
FormMessage,
} from "../ui/form";
import { Input } from "../ui/input";
import { useToast } from "../ui/use-toast";

const FormSchema = z.object({
todo: z
Expand All @@ -36,10 +35,8 @@ const TaskForm: FC<TaskFormProps> = ({ createTodo }) => {
resolver: zodResolver(FormSchema),
defaultValues: { todo: "", projectId: "" },
});
const { toast } = useToast();

const handleSubmit = ({ todo, projectId }: z.infer<typeof FormSchema>) => {
toast({ title: "You created a new task", description: "new task created" });
createTodo(todo, projectId !== "" ? projectId : undefined);
form.reset();
};
Expand Down
134 changes: 118 additions & 16 deletions components/dayplan/task.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,137 @@
import { DayPlanTodo } from "@/api/useDayplans";
import { cn } from "@/lib/utils";
import { FC } from "react";
import { IoCheckboxSharp, IoSquareOutline } from "react-icons/io5";
import { Edit, Trash } from "lucide-react";
import { FC, useState } from "react";
import ProjectName from "../ui-elements/tokens/project-name";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "../ui/alert-dialog";
import { Button } from "../ui/button";
import { Checkbox } from "../ui/checkbox";
import { Input } from "../ui/input";

type TaskProps = {
todo: DayPlanTodo;
switchTodoDone: (taskId: string, done: boolean) => void;
updateTodo: (todo: string, todoId: string) => void;
deleteTodo: (todoId: string) => void;
editable?: boolean;
};

const Task: FC<TaskProps> = ({
todo: { id, todo, done, projectId },
switchTodoDone,
updateTodo,
deleteTodo,
editable,
}) => {
const Icon = done ? IoCheckboxSharp : IoSquareOutline;
const [isEditing, setIsEditing] = useState(false);
const [todoValue, setTodoValue] = useState(todo);
const [alertOpen, setAlertOpen] = useState(false);

return (
<article className="flex flex-row mt-2 text-base md:text-lg ml-6 gap-2">
<Icon
className="mt-1 cursor-pointer"
onClick={() => switchTodoDone(id, done)}
/>
<div className={cn(done && "line-through")}>
<div>{todo}</div>
{projectId && (
<div className="text-muted-foreground">
<ProjectName projectId={projectId} />
</div>
)}
<div className="space-y-4">
<div className="items-top flex space-x-2 text-base md:text-lg">
<Checkbox
id={id}
checked={done}
onCheckedChange={() => switchTodoDone(id, done)}
className="mt-[0.2rem]"
/>
<div className="grid gap-1 leading-none">
<label
htmlFor={id}
className={cn(
"text-base md:text-xl peer-disabled:cursor-not-allowed peer-disabled:opacity-70 flex gap-2",
done && "line-through"
)}
>
{isEditing ? (
<>
<Input
value={todoValue}
onChange={(e) => {
setTodoValue(e.target.value);
}}
size={40}
/>
<Button
onClick={(event) => {
event.preventDefault();
updateTodo(todoValue, id);
setIsEditing(false);
}}
>
Confirm
</Button>
</>
) : (
<>
{todo}
{editable && (
<>
<Edit
className="w-4 h-4 mt-1 text-muted-foreground hover:text-primary"
onClick={(event) => {
event.preventDefault();
setIsEditing(true);
}}
/>
<AlertDialog open={alertOpen} onOpenChange={setAlertOpen}>
<AlertDialogTrigger asChild>
<Trash
className="w-4 h-4 mt-1 text-muted-foreground hover:text-primary"
onClick={(e) => {
e.preventDefault();
setAlertOpen(true);
}}
/>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
Delete confirmation
</AlertDialogTitle>
<AlertDialogDescription>
Confirm if you would like to delete the todo &quot;
{todo}&quot;.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={() => {
deleteTodo(id);
}}
>
Confirm
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
)}
</>
)}
</label>
{projectId && (
<div
className={cn("text-muted-foreground", done && "line-through")}
>
<ProjectName projectId={projectId} />
</div>
)}
</div>
</div>
</article>
</div>
);
};

Expand Down
Loading

0 comments on commit d59197b

Please sign in to comment.