diff --git a/apps/client/src/actions/clean-cache/index.ts b/apps/client/src/actions/clean-cache/index.ts new file mode 100644 index 0000000..cee89f4 --- /dev/null +++ b/apps/client/src/actions/clean-cache/index.ts @@ -0,0 +1,11 @@ +"use server"; + +import { revalidatePath } from "next/cache"; + +export async function cleanCache( + path: string, + type: "layout" | "page" = "page", +) { + console.log("cleaning cache of ", path); + revalidatePath(path, type); +} diff --git a/apps/client/src/app/app/entry/[id]/(components)/entry-title/entry-title.component.tsx b/apps/client/src/app/app/entry/[id]/(components)/entry-title/entry-title.component.tsx index 90da7ff..539afb8 100644 --- a/apps/client/src/app/app/entry/[id]/(components)/entry-title/entry-title.component.tsx +++ b/apps/client/src/app/app/entry/[id]/(components)/entry-title/entry-title.component.tsx @@ -5,6 +5,9 @@ import { EntryService } from "@/models/api/entry"; import type { Entry } from "@/types/entry"; import { useEffect, useRef, useState } from "react"; import { useEntryStore } from "../../(store)/entry-store"; +import { cleanCache } from "@/actions/clean-cache"; +import { ClientRoutingService } from "@/models/routing/client"; +import { useRouter } from "next/navigation"; export function EntryTitle({ defaultValue = "", @@ -24,6 +27,8 @@ export function EntryTitle({ const setEntryState = useEntryStore((state) => state.setState); + const router = useRouter(); + useEffect(() => { if (renderingTimes.current === 1) { renderingTimes.current++; @@ -46,8 +51,12 @@ export function EntryTitle({ } setEntryState("up to date"); + await cleanCache(ClientRoutingService.app.home, "layout"); + router.refresh(); } + if (defaultValue === debouncedTitle) return; + const ctrl = new AbortController(); // eslint-disable-next-line @typescript-eslint/no-floating-promises diff --git a/apps/client/src/components/feature/aside-nav/aside-nav.component.tsx b/apps/client/src/components/feature/aside-nav/aside-nav.component.tsx index bddbcf2..fa6a1d8 100644 --- a/apps/client/src/components/feature/aside-nav/aside-nav.component.tsx +++ b/apps/client/src/components/feature/aside-nav/aside-nav.component.tsx @@ -1,95 +1,29 @@ -"use client"; - import { Hr } from "@/components/ui/hr"; import { AsideNavLinks } from "./components/navlinks"; import { ProfileCard } from "./components/profile-card"; import { EntrySearchModalTrigger } from "../entry-search-modal/search-entry-modal-trigger"; -import { Command, Menu, X } from "lucide-react"; -import { - Drawer, - DrawerClose, - DrawerContent, - DrawerFooter, - DrawerHeader, - DrawerTrigger, -} from "../drawer"; -import { Button } from "@/components/ui/button"; -import { useAsideNavStore } from "./store"; -import { useEffect, useState } from "react"; +import { Command } from "lucide-react"; import { NewEntryBtn } from "./components/new-entry-btn"; +import { MobileAsideView } from "./views/mobile"; +import { DesktopAsideView } from "./views/desktop"; -export function AsideNav() { - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - - const canDrawerOpen = useAsideNavStore((state) => state.canDrawerOpen); - const closeDrawer = useAsideNavStore((state) => state.closeDrawer); - const openDrawer = useAsideNavStore((state) => state.openDrawer); - - function handleDrawerOpenChange(open: boolean) { - setIsDrawerOpen(open); - } - - function handleFocusOnDrawerBackground() { - closeDrawer(); - - setTimeout(() => { - openDrawer(); - }, 500); - } - - useEffect(() => { - if (!isDrawerOpen) return; - - document.getElementsByTagName("body")[0].style.overflowY = "hidden"; - - return () => { - document.getElementsByTagName("body")[0].style.overflowY = "auto"; - }; - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isDrawerOpen]); +const VIEWS = { + mobile: MobileAsideView, + desktop: DesktopAsideView, +}; +export function AsideNav() { return (
- +
- {isDrawerOpen && ( -
{ - e.stopPropagation(); - - handleFocusOnDrawerBackground(); - }} - className="h-screen w-full bg-black/40 absolute top-0 left-0 z-40" - >
- )} - - - - - - + + +
); diff --git a/apps/client/src/components/feature/aside-nav/components/entry-list/entry-item.component.tsx b/apps/client/src/components/feature/aside-nav/components/entry-list/entry-item.component.tsx new file mode 100644 index 0000000..31faf97 --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/components/entry-list/entry-item.component.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { ClientRoutingService } from "@/models/routing/client"; +import type { Entry } from "@/types/entry"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { useEffect, useState } from "react"; + +export function EntryItem({ entry }: { entry: Entry }) { + const [isActive, setIsActive] = useState(false); + + const pathName = usePathname(); + + useEffect(() => { + if (pathName === ClientRoutingService.app.entries.readById(entry.id)) { + setIsActive(true); + return; + } + + setIsActive(false); + }, [pathName, entry.id]); + + return ( + +
+ {entry.title} + + {new Date(entry.updated_at).toLocaleString()} + +
+ + ); +} diff --git a/apps/client/src/components/feature/aside-nav/components/entry-list/entry-list.component.tsx b/apps/client/src/components/feature/aside-nav/components/entry-list/entry-list.component.tsx new file mode 100644 index 0000000..ad4eac1 --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/components/entry-list/entry-list.component.tsx @@ -0,0 +1,33 @@ +import { EntryService } from "@/models/api/entry"; +import { EntryItem } from "./entry-item.component"; +import { getCookie } from "@/utils/getCookies"; + +export async function EntryList() { + const { cookie } = getCookie(); + + if (!cookie) return

something went wrong

; + + const { entryList, error } = await EntryService.getUserEntyList({ cookie }); + console.log(entryList); + + return ( + + ); +} diff --git a/apps/client/src/components/feature/aside-nav/components/entry-list/index.ts b/apps/client/src/components/feature/aside-nav/components/entry-list/index.ts new file mode 100644 index 0000000..d21a00b --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/components/entry-list/index.ts @@ -0,0 +1 @@ +export * from "./entry-list.component"; diff --git a/apps/client/src/components/feature/aside-nav/components/new-entry-btn/new-entry-btn.component.tsx b/apps/client/src/components/feature/aside-nav/components/new-entry-btn/new-entry-btn.component.tsx index 9a58c63..549d7b7 100644 --- a/apps/client/src/components/feature/aside-nav/components/new-entry-btn/new-entry-btn.component.tsx +++ b/apps/client/src/components/feature/aside-nav/components/new-entry-btn/new-entry-btn.component.tsx @@ -29,6 +29,7 @@ export function NewEntryBtn() { const url = ClientRoutingService.app.entries.readById(newEntryId); + router.refresh(); router.push(url); setLoading(false); diff --git a/apps/client/src/components/feature/aside-nav/views/desktop/desktop.view.component.tsx b/apps/client/src/components/feature/aside-nav/views/desktop/desktop.view.component.tsx new file mode 100644 index 0000000..0b0c0b2 --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/views/desktop/desktop.view.component.tsx @@ -0,0 +1,15 @@ +import { Hr } from "@/components/ui/hr"; +import { type ReactNode } from "react"; +import { EntryList } from "../../components/entry-list"; + +export function DesktopAsideView({ children }: { children: ReactNode }) { + return ( + <> + + + ); +} diff --git a/apps/client/src/components/feature/aside-nav/views/desktop/index.ts b/apps/client/src/components/feature/aside-nav/views/desktop/index.ts new file mode 100644 index 0000000..08c2da1 --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/views/desktop/index.ts @@ -0,0 +1 @@ +export * from "./desktop.view.component"; diff --git a/apps/client/src/components/feature/aside-nav/views/mobile/index.ts b/apps/client/src/components/feature/aside-nav/views/mobile/index.ts new file mode 100644 index 0000000..94e59fd --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/views/mobile/index.ts @@ -0,0 +1 @@ +export * from "./mobile.view.component"; diff --git a/apps/client/src/components/feature/aside-nav/views/mobile/mobile.view.component.tsx b/apps/client/src/components/feature/aside-nav/views/mobile/mobile.view.component.tsx new file mode 100644 index 0000000..c40b342 --- /dev/null +++ b/apps/client/src/components/feature/aside-nav/views/mobile/mobile.view.component.tsx @@ -0,0 +1,82 @@ +"use client"; + +import { Menu, X } from "lucide-react"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerFooter, + DrawerHeader, + DrawerTrigger, +} from "../../../drawer"; +import { Button } from "@/components/ui/button"; +import { useAsideNavStore } from "../../store"; +import { type ReactNode, useEffect, useState } from "react"; + +export function MobileAsideView({ children }: { children: ReactNode }) { + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + + const canDrawerOpen = useAsideNavStore((state) => state.canDrawerOpen); + const closeDrawer = useAsideNavStore((state) => state.closeDrawer); + const openDrawer = useAsideNavStore((state) => state.openDrawer); + + function handleDrawerOpenChange(open: boolean) { + setIsDrawerOpen(open); + } + + function handleFocusOnDrawerBackground() { + closeDrawer(); + + setTimeout(() => { + openDrawer(); + }, 500); + } + + useEffect(() => { + if (!isDrawerOpen) return; + + document.getElementsByTagName("body")[0].style.overflowY = "hidden"; + + return () => { + document.getElementsByTagName("body")[0].style.overflowY = "auto"; + }; + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isDrawerOpen]); + + return ( + <> + {isDrawerOpen && ( +
{ + e.stopPropagation(); + + handleFocusOnDrawerBackground(); + }} + className="h-screen w-full bg-black/40 absolute top-0 left-0 z-40" + >
+ )} + + + + + + + + ); +} diff --git a/apps/client/src/components/feature/delete-entry-modal/delete-entry-modal.component.tsx b/apps/client/src/components/feature/delete-entry-modal/delete-entry-modal.component.tsx index 58f2807..daea801 100644 --- a/apps/client/src/components/feature/delete-entry-modal/delete-entry-modal.component.tsx +++ b/apps/client/src/components/feature/delete-entry-modal/delete-entry-modal.component.tsx @@ -42,6 +42,7 @@ export function DeleteEntryModalTrigger({ if (pathName === ClientRoutingService.app.entries.readById(entryId)) { router.push(ClientRoutingService.app.home); + router.refresh(); return; } diff --git a/apps/client/src/models/api/entry/entry.model.ts b/apps/client/src/models/api/entry/entry.model.ts index c2248dc..eeaf39f 100644 --- a/apps/client/src/models/api/entry/entry.model.ts +++ b/apps/client/src/models/api/entry/entry.model.ts @@ -88,13 +88,20 @@ export class EntryService extends ApiService { public static async getUserEntyList({ signal, + cookie, }: { signal?: AbortSignal; + cookie?: string; }): Promise<{ entryList: Entry[] | null; error: string | null }> { try { const { status, data } = await axios.get( ApiRoutingService.routing.entry.getEntryList, - { ...(signal && { signal }) }, + { + ...(signal && { signal }), + headers: { + ...(cookie && { Cookie: cookie }), + }, + }, ); if (status !== 200)