Skip to content

Commit c052154

Browse files
author
Gianmarco
committed
added icon picker
1 parent 4b225f7 commit c052154

26 files changed

+1748
-36
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use client";
2+
3+
import Toolbar from "@/app/(main)/_components/Toolbar";
4+
import { api } from "@/convex/_generated/api";
5+
import { Id } from "@/convex/_generated/dataModel";
6+
import { useQuery } from "convex/react";
7+
import React from "react";
8+
9+
interface DocumentIdPageProps {
10+
params: {
11+
documentId: Id<"documents">;
12+
};
13+
}
14+
const DocumentIdPage = ({ params: { documentId } }: DocumentIdPageProps) => {
15+
const document = useQuery(api.documents.getById, {
16+
id: documentId,
17+
});
18+
19+
if (document === undefined) {
20+
return <div>Loading...</div>;
21+
}
22+
23+
if (document === null) {
24+
return <div>Not found</div>;
25+
}
26+
27+
return (
28+
<div className="pb-40">
29+
<div className="h-[35vh]" />
30+
<div className="md:max-w-3xl lg:max-w-4xl mx-auto">
31+
<Toolbar initialData={document} />
32+
</div>
33+
</div>
34+
);
35+
};
36+
export default DocumentIdPage;

app/(main)/_components/Banner.tsx

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"use client";
2+
3+
import ConfirmModal from "@/components/modals/ConfirmModal";
4+
import { Button } from "@/components/ui/button";
5+
import { api } from "@/convex/_generated/api";
6+
import { Id } from "@/convex/_generated/dataModel";
7+
import { useMutation } from "convex/react";
8+
import { useRouter } from "next/navigation";
9+
import React from "react";
10+
import { toast } from "sonner";
11+
12+
interface BannerProps {
13+
documentId: Id<"documents">;
14+
}
15+
16+
const Banner = (props: BannerProps) => {
17+
const { documentId } = props;
18+
const router = useRouter();
19+
const remove = useMutation(api.documents.remove);
20+
const restore = useMutation(api.documents.restore);
21+
22+
const onRemove = () => {
23+
const promise = remove({ id: documentId })
24+
25+
toast.promise(promise, {
26+
loading: "Removing note...",
27+
success: "Note Removed",
28+
error: "Failed to remove",
29+
});
30+
31+
router.push("/documents");
32+
};
33+
34+
const onRestore = () => {
35+
const promise = restore({ id: documentId });
36+
toast.promise(promise, {
37+
loading: "Restoring note...",
38+
success: "Note Restored",
39+
error: "Failed to restore",
40+
});
41+
};
42+
43+
return (
44+
<div className="w-full bg-rose-500 text-center text-sm p-2 text-white flex items-center gap-x-2 justify-center">
45+
<p>This note has been archived</p>
46+
<Button
47+
size={"sm"}
48+
onClick={onRestore}
49+
variant={"outline"}
50+
className="border-white bg-transparent hover:bg-primary/5 text-white hover:text-white p-1 px-2 h-auto font-normal"
51+
>
52+
Restore note
53+
</Button>
54+
<ConfirmModal onConfirm={onRemove}>
55+
<Button
56+
size={"sm"}
57+
variant={"outline"}
58+
className="border-white bg-transparent hover:bg-primary/5 text-white hover:text-white p-1 px-2 h-auto font-normal"
59+
>
60+
Delete forever
61+
</Button>
62+
</ConfirmModal>
63+
</div>
64+
);
65+
};
66+
67+
export default Banner;

app/(main)/_components/Item.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ const Item = (props: ItemProps) => {
111111
>
112112
{!!id && (
113113
<div
114-
className="h-full rounded-sm hover:bg-neutral-300 dark:bg-neutral-600 mr-1"
114+
className="h-full rounded-sm hover:bg-neutral-300 dark:hover:bg-neutral-600 mr-1"
115115
role="button"
116116
onClick={handleExpand}
117117
>
@@ -164,7 +164,7 @@ const Item = (props: ItemProps) => {
164164
<div
165165
role="button"
166166
onClick={onCreate}
167-
className="opacity-0 group-hover:opacity-100 h-full ml-auto rounded-sm hover:bg-neutral-300 dark:bg-neutral-600"
167+
className="opacity-0 group-hover:opacity-100 h-full ml-auto rounded-sm hover:bg-neutral-300 hover:dark:bg-neutral-600"
168168
>
169169
<Plus className="w-4 h-4 text-muted-foreground" />
170170
</div>

app/(main)/_components/Menu.tsx

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"use client";
2+
3+
import React from "react";
4+
import {
5+
DropdownMenu,
6+
DropdownMenuContent,
7+
DropdownMenuSeparator,
8+
DropdownMenuItem,
9+
DropdownMenuTrigger,
10+
} from "@/components/ui/dropdown-menu";
11+
import { useRouter } from "next/navigation";
12+
import { useUser } from "@clerk/clerk-react";
13+
import { useMutation } from "convex/react";
14+
import { api } from "@/convex/_generated/api";
15+
import { toast } from "sonner";
16+
import { Id } from "@/convex/_generated/dataModel";
17+
import { Button } from "@/components/ui/button";
18+
import { MoreHorizontal, Trash } from "lucide-react";
19+
import { Skeleton } from "@/components/ui/skeleton";
20+
21+
interface MenuProps {
22+
documentId: Id<"documents">;
23+
}
24+
25+
const Menu = (props: MenuProps) => {
26+
const { documentId } = props;
27+
const router = useRouter();
28+
const { user } = useUser();
29+
const archive = useMutation(api.documents.archive);
30+
31+
const onArchive = () => {
32+
const promise = archive({ id: documentId });
33+
toast.promise(promise, {
34+
loading: "Archiving...",
35+
success: "Archived",
36+
error: "Failed to archive",
37+
});
38+
39+
router.push("/documents");
40+
};
41+
42+
return (
43+
<DropdownMenu>
44+
<DropdownMenuTrigger>
45+
<Button size={"sm"} variant={"outline"} className="ghost">
46+
<MoreHorizontal className="h-4 w-4" />
47+
</Button>
48+
</DropdownMenuTrigger>
49+
<DropdownMenuContent
50+
className="w-60"
51+
align="end"
52+
alignOffset={8}
53+
forceMount
54+
>
55+
<DropdownMenuItem onClick={onArchive}>
56+
<Trash className="h-4 w-4 mr-2" />
57+
Delete
58+
</DropdownMenuItem>
59+
<DropdownMenuSeparator />
60+
<div className="text-xs text-muted-foreground p-2">
61+
Last edited by {user?.fullName}
62+
</div>
63+
</DropdownMenuContent>
64+
</DropdownMenu>
65+
);
66+
};
67+
68+
Menu.Skeleton = function MenuSkeleton() {
69+
return (
70+
<Skeleton className="h-10 w-10" />
71+
)
72+
}
73+
74+
export default Menu;

app/(main)/_components/Navbar.tsx

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"use client";
2+
3+
import { api } from "@/convex/_generated/api";
4+
import { Id } from "@/convex/_generated/dataModel";
5+
import { useQuery } from "convex/react";
6+
import { MenuIcon } from "lucide-react";
7+
import { useParams } from "next/navigation";
8+
import React from "react";
9+
import Title from "./Title";
10+
import Banner from "./Banner";
11+
import Menu from "./Menu";
12+
13+
interface NavbarProps {
14+
isCollapsed: boolean;
15+
onResetWidth: () => void;
16+
}
17+
18+
const Navbar = (props: NavbarProps) => {
19+
const { isCollapsed, onResetWidth } = props;
20+
const params = useParams();
21+
const document = useQuery(api.documents.getById, {
22+
id: params.documentId as Id<"documents">,
23+
});
24+
25+
if (document === undefined) {
26+
return (
27+
<nav className="bg-background dark:bg-[#1F1F1F] px-3 py-2 w-full flex items-center justify-between">
28+
<Title.Skeleton />
29+
<div className="flex items-center gap-x-2">
30+
<Menu.Skeleton/>
31+
</div>
32+
</nav>
33+
);
34+
}
35+
36+
if (document === null) {
37+
return <p>Not found</p>;
38+
}
39+
40+
return (
41+
<>
42+
<nav className="bg-background dark:bg-[#1F1F1F] px-3 py-2 w-full flex items-center gap-x-4">
43+
{isCollapsed && (
44+
<MenuIcon
45+
role="button"
46+
onClick={onResetWidth}
47+
className="h-6 w-6 text-muted-foreground"
48+
/>
49+
)}
50+
<div className="flex items-center justify-between w-full">
51+
<Title initialData={document} />
52+
<div className="flex items-center gap-x-2">
53+
<Menu documentId={document._id} />
54+
</div>
55+
</div>
56+
</nav>
57+
{document.isArchived && <Banner documentId={document._id} />}
58+
</>
59+
);
60+
};
61+
62+
export default Navbar;

app/(main)/_components/Navigation.tsx

+22-21
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
Settings,
1010
Trash,
1111
} from "lucide-react";
12-
import { usePathname } from "next/navigation";
12+
import { useParams, usePathname } from "next/navigation";
1313
import { ElementRef, useEffect, useRef, useState } from "react";
1414
import { useMediaQuery } from "usehooks-ts";
1515
import UserItem from "./UserItem";
@@ -21,8 +21,14 @@ import DocumentList from "./DocumentList";
2121
import { Popover, PopoverContent } from "@/components/ui/popover";
2222
import { PopoverTrigger } from "@radix-ui/react-popover";
2323
import TrashBox from "./TrashBox";
24+
import { useSearch } from "@/hooks/use-search";
25+
import { useSettings } from "@/hooks/use-settings";
26+
import Navbar from "./Navbar";
2427

2528
const Navigation = () => {
29+
const search = useSearch();
30+
const settings = useSettings();
31+
const params = useParams();
2632
const pathname = usePathname();
2733
const isMobile = useMediaQuery("(max-width: 768px)");
2834
const create = useMutation(api.documents.create);
@@ -147,17 +153,8 @@ const Navigation = () => {
147153
</div>
148154
<div>
149155
<UserItem />
150-
<Item
151-
label="Search"
152-
icon={Search}
153-
isSearch
154-
onClick={() => console.log("search")}
155-
/>
156-
<Item
157-
label="Settings"
158-
icon={Settings}
159-
onClick={() => console.log("settings")}
160-
/>
156+
<Item label="Search" icon={Search} isSearch onClick={search.onOpen} />
157+
<Item label="Settings" icon={Settings} onClick={settings.onOpen} />
161158
<Item onClick={handleCreate} label="New Page" icon={PlusCircle} />
162159
</div>
163160
<div className="mt-4">
@@ -191,15 +188,19 @@ const Navigation = () => {
191188
isMobile && "left-0 w-full"
192189
)}
193190
>
194-
<nav className="bg-transparent px-3 py-2 w-full">
195-
{isCollapsed && (
196-
<MenuIcon
197-
onClick={resetWidth}
198-
className="w-6 h-6 text-muted-foreground"
199-
role="button"
200-
/>
201-
)}
202-
</nav>
191+
{!!params.documentId ? (
192+
<Navbar isCollapsed={isCollapsed} onResetWidth={resetWidth} />
193+
) : (
194+
<nav className="bg-transparent px-3 py-2 w-full">
195+
{isCollapsed && (
196+
<MenuIcon
197+
onClick={resetWidth}
198+
className="w-6 h-6 text-muted-foreground"
199+
role="button"
200+
/>
201+
)}
202+
</nav>
203+
)}
203204
</div>
204205
</>
205206
);

0 commit comments

Comments
 (0)