Skip to content
306 changes: 231 additions & 75 deletions src/components/drawer-event-task.tsx

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions src/components/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable i18next/no-literal-string */
"use client";

import { useEffect, useState } from "react";
import { useEffect, useState, type CSSProperties } from "react";
import {
Moon,
Sun,
Expand Down Expand Up @@ -219,7 +219,14 @@ export default function Sidebar() {

<SheetContent
side="right"
className="w-[85%] sm:max-w-sm p-5 flex-col flex justify-between border-none oled:bg-black"
className="w-[85%] sm:max-w-sm flex flex-col justify-between border-none oled:bg-black px-5 pb-5 pt-[var(--sidebar-safe-area-top)]"
style={
{
"--sidebar-safe-area-top": "calc(var(--safe-area-top) + 12px)",
"--sheet-close-top": "calc(var(--safe-area-top) + 14px)",
"--sheet-close-right": "24px",
} as CSSProperties
}
>
<SheetHeader>
<SheetTitle>{t("sidebar.title")}</SheetTitle>
Expand Down
9 changes: 7 additions & 2 deletions src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,13 @@ const SheetContent = React.forwardRef<
{...props}
>
{children}
<SheetPrimitive.Close className="absolute right-4 top-safe-or-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<SheetPrimitive.Close
className="absolute right-[var(--sheet-close-right,calc(var(--safe-area-right,0px)+1rem))]
top-[var(--sheet-close-top,calc(var(--safe-area-top,0px)+1rem))] flex h-2rem w-2rem]
items-center justify-center rounded-sm opacity-70 ring-offset-background transition-all hover:opacity-100
focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
>
<X className="h-[1.5rem] w-[1.5rem]" />
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
Expand Down
117 changes: 62 additions & 55 deletions src/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,74 @@
"use client"
"use client";

import { useTheme } from "@/components/theme-provider"
import { Toaster as Sonner } from "sonner"
import { useTheme } from "@/components/theme-provider";
import { Toaster as Sonner } from "sonner";

type ToasterProps = React.ComponentProps<typeof Sonner>
type ToasterProps = React.ComponentProps<typeof Sonner>;

type OffsetObject = Exclude<ToasterProps["offset"], string | number>
type OffsetObject = Exclude<ToasterProps["offset"], string | number>;

const SAFE_AREA_OFFSET: OffsetObject = {
top: "calc(var(--safe-area-top, 50px) + 1rem)",
right: "calc(var(--safe-area-right, 0px) + 1rem)",
bottom: "calc(var(--safe-area-bottom, 30px) + 1rem)",
left: "calc(var(--safe-area-left, 0px) + 1rem)",
}
top: "calc(var(--safe-area-top, 50px) + 1rem)",
right: "calc(var(--safe-area-right, 0px) + 1rem)",
bottom: "calc(var(--safe-area-bottom, 30px) + 1rem)",
left: "calc(var(--safe-area-left, 0px) + 1rem)",
};

const mergeClassName = (base: string, extra?: string) =>
[base, extra].filter(Boolean).join(" ")
[base, extra].filter(Boolean).join(" ");

const resolveOffset = (value?: ToasterProps["offset"]): ToasterProps["offset"] => {
if (!value) return { ...SAFE_AREA_OFFSET }
if (typeof value === "number" || typeof value === "string") return value
return {
...SAFE_AREA_OFFSET,
...value,
}
}
const resolveOffset = (
value?: ToasterProps["offset"]
): ToasterProps["offset"] => {
if (!value) return { ...SAFE_AREA_OFFSET };
if (typeof value === "number" || typeof value === "string") return value;
return {
...SAFE_AREA_OFFSET,
...value,
};
};

const Toaster = ({ toastOptions, offset, mobileOffset, ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
const Toaster = ({
toastOptions,
offset,
mobileOffset,
...props
}: ToasterProps) => {
const { theme = "system" } = useTheme();

const mergedToastOptions: ToasterProps["toastOptions"] = {
...toastOptions,
classNames: {
...toastOptions?.classNames,
toast: mergeClassName(
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
toastOptions?.classNames?.toast
),
description: mergeClassName(
"group-[.toast]:text-muted-foreground",
toastOptions?.classNames?.description
),
actionButton: mergeClassName(
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
toastOptions?.classNames?.actionButton
),
cancelButton: mergeClassName(
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
toastOptions?.classNames?.cancelButton
),
},
}
const mergedToastOptions: ToasterProps["toastOptions"] = {
...toastOptions,
classNames: {
...toastOptions?.classNames,
toast: mergeClassName(
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
toastOptions?.classNames?.toast
),
description: mergeClassName(
"group-[.toast]:text-muted-foreground",
toastOptions?.classNames?.description
),
actionButton: mergeClassName(
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
toastOptions?.classNames?.actionButton
),
cancelButton: mergeClassName(
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
toastOptions?.classNames?.cancelButton
),
},
};

return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={mergedToastOptions}
offset={resolveOffset(offset)}
mobileOffset={resolveOffset(mobileOffset)}
{...props}
/>
)
}
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={mergedToastOptions}
offset={resolveOffset(offset)}
mobileOffset={resolveOffset(mobileOffset)}
{...props}
/>
);
};

export { Toaster }
export { Toaster };
31 changes: 27 additions & 4 deletions src/lib/utils/agenda.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { TaskData } from "@/types/data";
import { getFromStorage, saveToStorage } from "./storage";

type StoredTask = Omit<TaskData, "date"> & { date: string };

export function saveTaskToLocalStorage({ task }: { task: TaskData }) {
const existingTasks = JSON.parse(
getFromStorage("tasks") ?? "[]"
) as TaskData[];
existingTasks.push(task);
) as StoredTask[];
existingTasks.push({
...task,
date: new Date(task.date).toISOString(),
});
saveToStorage("tasks", JSON.stringify(existingTasks));
}

export function getTasksFromLocalStorage(): TaskData[] {
const tasks = JSON.parse(getFromStorage("tasks") ?? "[]") as TaskData[];
const tasks = JSON.parse(getFromStorage("tasks") ?? "[]") as StoredTask[];
return tasks.map((task) => ({
...task,
date: new Date(task.date),
Expand All @@ -20,7 +25,25 @@ export function getTasksFromLocalStorage(): TaskData[] {
export function removeTaskFromLocalStorage({ taskId }: { taskId: string }) {
const existingTasks = JSON.parse(
getFromStorage("tasks") ?? "[]"
) as TaskData[];
) as StoredTask[];
const updatedTasks = existingTasks.filter((task) => task.id !== taskId);
saveToStorage("tasks", JSON.stringify(updatedTasks));
}

export function updateTaskInLocalStorage({ task }: { task: TaskData }) {
const existingTasks = JSON.parse(
getFromStorage("tasks") ?? "[]"
) as StoredTask[];

const updatedTasks = existingTasks.map((storedTask) =>
storedTask.id === task.id
? {
...storedTask,
task: task.task,
date: new Date(task.date).toISOString(),
}
: storedTask
);

saveToStorage("tasks", JSON.stringify(updatedTasks));
}
8 changes: 7 additions & 1 deletion src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@
"taskDescription": "Enter the title",
"date": "Date",
"hour": "Hour",
"createTaskBtn": "Create task"
"createTaskBtn": "Create task",
"markTaskDone": "Mark as done",
"undoTaskCompletion": "Undo completion",
"editTaskTitle": "Edit task",
"updateTaskBtn": "Update task",
"taskUpdated": "Task updated",
"taskUpdatedDescription": "Your changes have been saved."
},
"associationsPage": {
"search": "Find an association",
Expand Down
8 changes: 7 additions & 1 deletion src/locales/es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@
"taskDescription": "Introduce el título",
"date": "Fecha",
"hour": "Hora",
"createTaskBtn": "Crear tarea"
"createTaskBtn": "Crear tarea",
"markTaskDone": "Marcar como completada",
"undoTaskCompletion": "Deshacer la finalización",
"editTaskTitle": "Editar tarea",
"updateTaskBtn": "Actualizar tarea",
"taskUpdated": "Tarea actualizada",
"taskUpdatedDescription": "Los cambios se han guardado."
},
"associationsPage": {
"search": "Buscar una asociación",
Expand Down
8 changes: 7 additions & 1 deletion src/locales/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@
"taskDescription": "Entrez le titre",
"date": "Date",
"hour": "Heure",
"createTaskBtn": "Créer la tâche"
"createTaskBtn": "Créer la tâche",
"markTaskDone": "Marquer comme effectuée",
"undoTaskCompletion": "Annuler la complétion",
"editTaskTitle": "Modifier la tâche",
"updateTaskBtn": "Mettre à jour la tâche",
"taskUpdated": "Tâche mise à jour",
"taskUpdatedDescription": "Les modifications ont été enregistrées."
},
"associationsPage": {
"search": "Rechercher une association",
Expand Down
Loading