Skip to content

Commit

Permalink
Merge pull request #231 from huilensolis/227-feat-add-entry-list-to-s…
Browse files Browse the repository at this point in the history
…idebar

227 feat add entry list to sidebar
  • Loading branch information
huilensolis authored Sep 6, 2024
2 parents 1cab562 + 3bcd707 commit 9712ad6
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 80 deletions.
11 changes: 11 additions & 0 deletions apps/client/src/actions/clean-cache/index.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "",
Expand All @@ -24,6 +27,8 @@ export function EntryTitle({

const setEntryState = useEntryStore((state) => state.setState);

const router = useRouter();

useEffect(() => {
if (renderingTimes.current === 1) {
renderingTimes.current++;
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<boolean>(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 (
<div className="bg-zinc-100">
<div className="hidden lg:flex">
<aside className="max-w-80 w-full h-full min-h-screen p-2 flex gap-2 flex-col items-center border-r border-neutral-300">
<VIEWS.desktop>
<MenuItems />
</aside>
</VIEWS.desktop>
</div>
<div className="lg:hidden bg-zinc-100 border-b border-gray-200 p-2">
{isDrawerOpen && (
<div
onClick={(e) => {
e.stopPropagation();

handleFocusOnDrawerBackground();
}}
className="h-screen w-full bg-black/40 absolute top-0 left-0 z-40"
></div>
)}
<Drawer
open={canDrawerOpen ? undefined : false}
modal={false}
onOpenChange={handleDrawerOpenChange}
>
<DrawerTrigger asChild>
<Button variant="ghost" className="hover:bg-zinc-200 px-1.5">
<Menu className="h-8 w-8" />
</Button>
</DrawerTrigger>
<DrawerContent hidden={!canDrawerOpen}>
<DrawerHeader className="flex items-center justify-start">
<DrawerClose asChild>
<Button variant="ghost" className="px-1.5">
<X className="h-8 w-8" />
</Button>
</DrawerClose>
</DrawerHeader>
<DrawerFooter>
<MenuItems />
</DrawerFooter>
</DrawerContent>
</Drawer>
<VIEWS.mobile>
<MenuItems />
</VIEWS.mobile>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<boolean>(false);

const pathName = usePathname();

useEffect(() => {
if (pathName === ClientRoutingService.app.entries.readById(entry.id)) {
setIsActive(true);
return;
}

setIsActive(false);
}, [pathName, entry.id]);

return (
<Link href={ClientRoutingService.app.entries.readById(entry.id)}>
<article
className={`flex flex-col p-2 hover:bg-zinc-200 ${isActive ? "bg-zinc-200" : ""} rounded-sm transition-all duration-150`}
>
<span className="font-semibold">{entry.title}</span>
<span className="text-sm">
{new Date(entry.updated_at).toLocaleString()}
</span>
</article>
</Link>
);
}
Original file line number Diff line number Diff line change
@@ -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 <p>something went wrong</p>;

const { entryList, error } = await EntryService.getUserEntyList({ cookie });
console.log(entryList);

return (
<ul className="w-full flex flex-col gap-2">
{!error &&
entryList &&
entryList.length > 0 &&
entryList
.sort((entry, nextEntry) =>
new Date(entry.updated_at).getTime() >
new Date(nextEntry.updated_at).getTime()
? -1
: 1,
)
.map((entry) => (
<li key={entry.id}>
<EntryItem entry={entry} />
</li>
))}
{error && <p>something went wrong</p>}
</ul>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./entry-list.component";
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function NewEntryBtn() {

const url = ClientRoutingService.app.entries.readById(newEntryId);

router.refresh();
router.push(url);

setLoading(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<>
<aside className="max-w-80 w-full h-full min-h-screen p-2 flex gap-2 flex-col items-center border-r border-neutral-300">
{children}
<Hr orientation="horizontal" className="my-1" />
<EntryList />
</aside>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./desktop.view.component";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./mobile.view.component";
Original file line number Diff line number Diff line change
@@ -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<boolean>(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 && (
<div
onClick={(e) => {
e.stopPropagation();

handleFocusOnDrawerBackground();
}}
className="h-screen w-full bg-black/40 absolute top-0 left-0 z-40"
></div>
)}
<Drawer
open={canDrawerOpen ? undefined : false}
modal={false}
onOpenChange={handleDrawerOpenChange}
>
<DrawerTrigger asChild>
<Button variant="ghost" className="hover:bg-zinc-200 px-1.5">
<Menu className="h-8 w-8" />
</Button>
</DrawerTrigger>
<DrawerContent hidden={!canDrawerOpen}>
<DrawerHeader className="flex items-center justify-start">
<DrawerClose asChild>
<Button variant="ghost" className="px-1.5">
<X className="h-8 w-8" />
</Button>
</DrawerClose>
</DrawerHeader>
<DrawerFooter>{children}</DrawerFooter>
</DrawerContent>
</Drawer>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function DeleteEntryModalTrigger({

if (pathName === ClientRoutingService.app.entries.readById(entryId)) {
router.push(ClientRoutingService.app.home);
router.refresh();
return;
}

Expand Down
9 changes: 8 additions & 1 deletion apps/client/src/models/api/entry/entry.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Entry[]>(
ApiRoutingService.routing.entry.getEntryList,
{ ...(signal && { signal }) },
{
...(signal && { signal }),
headers: {
...(cookie && { Cookie: cookie }),
},
},
);

if (status !== 200)
Expand Down

0 comments on commit 9712ad6

Please sign in to comment.