Skip to content

Commit

Permalink
feat: notes page
Browse files Browse the repository at this point in the history
  • Loading branch information
listlessbird committed Oct 28, 2024
1 parent 081db27 commit a0de964
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 21 deletions.
6 changes: 6 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ const nextConfig = {
dangerouslyAllowSVG: true,
contentDispositionType: "attachment",
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
remotePatterns: [
{
protocol: "https",
hostname: "*.googleusercontent.com",
},
],
},
output: "standalone",
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "NODE_OPTIONS='--inspect' next dev",
"dev": "docker compose -fcompose.dev.yml up -d && NODE_OPTIONS='--inspect' next dev",
"turbo": "NODE_OPTIONS=--inspect next dev --turbo",
"build": "next build",
"start": "next start",
Expand Down
Binary file added public/notes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { Bookmark, Brush, List, NotebookPen, Plus } from "lucide-react"
import { getRandomDark } from "@/lib/utils"
import { DashboardActionButton } from "@/app/_components/DashboardActionButton"

import { UserIndicator, WelcomeMessage } from "./user-indicator"
import { UserButton, WelcomeMessage } from "./user-indicator"

export default async function Dashboard() {
const UserIndicatorColor = getRandomDark()
const iconSize = 20

return (
<div className="relative">
<UserIndicator indicatorColor={`${UserIndicatorColor}`} />
<UserButton />
<div className="mt-3 space-y-4 p-4 lg:mt-10">
<WelcomeMessage />

Expand Down
14 changes: 4 additions & 10 deletions src/app/(dashboard)/dashboard/user-indicator.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client"

import { useMemo } from "react"
import Image from "next/image"

import { getInitials } from "@/lib/utils"
import { useSession } from "@/hooks/use-session"
import { Avatar } from "@/components/ui/avatar"
import { Avatar, AvatarImage } from "@/components/ui/avatar"
import {
DropdownMenu,
DropdownMenuContent,
Expand All @@ -13,10 +14,9 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import Typography from "@/components/ui/typography"
import { UIAvatar } from "@/components/ui-avatar"
import { logOut } from "@/app/(auth)/action"

export function UserIndicator({ indicatorColor }: { indicatorColor: string }) {
export function UserButton() {
const { user } = useSession()

const userInitials = useMemo(
Expand All @@ -29,13 +29,7 @@ export function UserIndicator({ indicatorColor }: { indicatorColor: string }) {
<DropdownMenu>
<DropdownMenuTrigger>
<Avatar asChild>
<UIAvatar
alt={user?.username || ""}
text={userInitials}
className="text-white"
size={48}
indicatorColor={indicatorColor}
/>
<AvatarImage src={user?.picture} alt={user?.username} />
</Avatar>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
Expand Down
11 changes: 11 additions & 0 deletions src/app/(notes)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { validateRequest } from "@/lib/auth"
import { NotesProviders } from "@/app/(notes)/providers"

export default async function NotesLayout({
children,
}: {
children: React.ReactNode
}) {
const { user } = await validateRequest()
return <NotesProviders user={user}>{children}</NotesProviders>
}
158 changes: 158 additions & 0 deletions src/app/(notes)/notes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
"use client"

import { useState } from "react"
import Image from "next/image"
import { Menu, MoreVertical, Plus, Search } from "lucide-react"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { ScrollArea } from "@/components/ui/scroll-area"
import { MaxWidthWrapper } from "@/components/max-width-wrapper"
import { UserButton } from "@/app/(dashboard)/dashboard/user-indicator"

export default function Page() {
return <NotesPage />
}

interface Note {
id: string
title: string
lastEdited: string
thumbnail: string
}

const templateNotes: Note[] = [
{
id: "t1",
title: "Blank note",
lastEdited: "",
thumbnail: "/notes.png",
},
]

export function NotesPage() {
// dummy for now
const [recentNotes, setRecentNotes] = useState<Note[]>([
{
id: "1",
title: "Work Notes",
lastEdited: "Edited Oct 26",
thumbnail: "/notes.png",
},
{
id: "2",
title: "Personal Goals",
lastEdited: "Edited Oct 25",
thumbnail: "/notes.png",
},
{
id: "3",
title: "Recipe Ideas",
lastEdited: "Edited Oct 24",
thumbnail: "/notes.png",
},
])

return (
<div className="flex h-screen flex-col">
<header className="flex items-center justify-between border-b p-4">
<div className="flex items-center">
<h1 className="text-xl font-semibold">Keeparr/Notes</h1>
</div>
<div className="relative">
<Search className="absolute left-2 top-2.5 size-4 text-muted-foreground" />
<Input type="search" placeholder="Search" className="w-64 pl-8" />
</div>
<div className="flex items-center space-x-2">
<Button size="icon" variant="ghost">
<UserButton />
</Button>
</div>
</header>
<MaxWidthWrapper>
<main className="flex-1 overflow-auto p-6">
<section className="mb-8">
<div className="mb-4 flex items-center justify-between">
<h2 className="text-lg font-semibold">Start a new note</h2>
</div>
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5">
{templateNotes.map((note) => (
<Card
key={note.id}
className="cursor-pointer transition-colors hover:bg-accent"
>
<CardContent className="p-0">
<Image
src={note.thumbnail}
alt={note.title}
className="h-32 w-full object-cover"
width={240}
height={240}
/>
</CardContent>
<CardFooter className="p-2">
<p className="text-sm">{note.title}</p>
</CardFooter>
</Card>
))}
</div>
</section>

<section>
<div className="mb-4 flex items-center justify-between">
<h2 className="text-lg font-semibold">Recent notes</h2>
</div>
<ScrollArea className="h-[calc(100vh-400px)]">
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
{recentNotes.map((note) => (
<Card
key={note.id}
className="cursor-pointer transition-colors hover:bg-accent"
>
<CardContent className="p-0">
<Image
src={note.thumbnail}
alt={note.title}
className="h-32 w-full object-cover"
width={120}
height={120}
/>
</CardContent>
<CardFooter className="flex items-center justify-between p-2">
<div>
<p className="text-sm font-medium">{note.title}</p>
<p className="text-xs text-muted-foreground">
{note.lastEdited}
</p>
</div>
<Button variant="ghost" size="icon">
<MoreVertical className="size-4" />
</Button>
</CardFooter>
</Card>
))}
</div>
</ScrollArea>
</section>
</main>
</MaxWidthWrapper>

<Button
size="lg"
className="fixed bottom-8 right-8 rounded-full shadow-lg"
onClick={() => {
const newNote = {
id: (recentNotes.length + 1).toString(),
title: "Untitled Note",
lastEdited: "Just now",
thumbnail: "/placeholder.svg?height=160&width=120",
}
setRecentNotes([newNote, ...recentNotes])
}}
>
<Plus className="mr-2 h-4 w-4" /> New Note
</Button>
</div>
)
}
12 changes: 12 additions & 0 deletions src/app/(notes)/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"use client"

import { ComponentProps, PropsWithChildren } from "react"

import { SessionProvider } from "@/hooks/use-session"

export function NotesProviders({
children,
user,
}: PropsWithChildren<ComponentProps<typeof SessionProvider>["value"]>) {
return <SessionProvider value={{ user }}>{children}</SessionProvider>
}
12 changes: 4 additions & 8 deletions src/app/_components/DashboardActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ export function DashboardActionButton({
}: { Icon: ReactNode; text: ReactNode; href?: string } & React.ComponentProps<
typeof Button
>) {
const customAction = typeof props.onClick === "function"
console.log({ customAction, onClick: props.onClick })
return (
<div className="flex gap-2">
<Button
Expand All @@ -23,13 +21,11 @@ export function DashboardActionButton({
// asChild={!customAction}
>
<div className="flex flex-col items-center justify-center gap-0">
{!customAction && (
<Link href={href ?? "/dashboard"}>
{Icon}
<Link href={href ?? "/dashboard"}>
{Icon}

<span className="sr-only">{text}</span>
</Link>
)}
<span className="sr-only">{text}</span>
</Link>
{/* {customAction && (
<div className="flex size-8 flex-col items-center justify-center">
{Icon}
Expand Down

0 comments on commit a0de964

Please sign in to comment.