Skip to content

Commit

Permalink
develop notes
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaosen7 committed Jul 22, 2024
1 parent fa7a268 commit afa8b88
Show file tree
Hide file tree
Showing 137 changed files with 2,590 additions and 559 deletions.
13 changes: 12 additions & 1 deletion apps/notes/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@ import sharedConfig from "@npc/storybook-config";

const config: StorybookConfig = {
...sharedConfig,
stories: ["./stories/**/*.stories.tsx"],
stories: ["../src/stories/**/*.stories.tsx"],
staticDirs: ["../public"],
webpackFinal(config) {
const fileLoaderRule = config.module?.rules?.find((rule) =>
(rule as any).test?.test?.(".svg"),
) as any;
config.module?.rules?.push({
test: /\.svg$/,
use: ["@svgr/webpack"],
});
fileLoaderRule.exclude = /\.svg$/i;
return config;
},
};

export default config;
6 changes: 3 additions & 3 deletions apps/notes/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { nunito } from "@/font";
import { ETheme, SyncElementClass, useTheme } from "@/theme";
import { DARK, LIGHT } from "@/theme/variables";
import { nunito } from "@libs/font";
import { ETheme, SyncElementClass, useTheme } from "@libs/theme";
import { DARK, LIGHT } from "@libs/theme/variables";
import {
INITIAL_VIEWPORTS,
MINIMAL_VIEWPORTS,
Expand Down
14 changes: 0 additions & 14 deletions apps/notes/.storybook/stories/button/icon.stories.tsx

This file was deleted.

11 changes: 0 additions & 11 deletions apps/notes/.storybook/stories/note/edit.stories.tsx

This file was deleted.

14 changes: 0 additions & 14 deletions apps/notes/.storybook/stories/search/input.stories.tsx

This file was deleted.

27 changes: 27 additions & 0 deletions apps/notes/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
webpack(config) {
// Grab the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.(".svg")
);

config.module.rules.push(
// Reapply the existing rule, but only for svg imports ending in ?url
{
...fileLoaderRule,
test: /\.svg$/i,
resourceQuery: /url/, // *.svg?url
},
// Convert all other *.svg imports to React components
{
test: /\.svg$/i,
issuer: fileLoaderRule.issuer,
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
use: ["@svgr/webpack"],
}
);

// Modify the file loader rule to ignore *.svg, since we have it handled now.
fileLoaderRule.exclude = /\.svg$/i;

return config;
},
};

export default nextConfig;
8 changes: 5 additions & 3 deletions apps/notes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
"start": "next start",
"storybook": "storybook dev -p 6006",
"build:storybook": "storybook build",
"lint": "next lint",
"lint": "eslint .",
"test:e2e": "playwright test",
"test": "vitest --run",
"test:watch": "vitest watch",
"test:changed": "vitest run --changed",
"prisma:studio": "dotenv -e .env.development -- prisma studio -b false",
"check-types": "tsc --noEmit",
"postinstall": "npc generate-components --templatesDir ./templates --outDir ./src/libs/assets --publicDir ./public"
"generate:components": "npc generate-components --templatesDir ./templates --outDir ./src/libs/components --publicDir ./src/assets"
},
"dependencies": {
"@clerk/nextjs": "^5.2.3",
Expand All @@ -32,7 +32,8 @@
"next": "14.2.5",
"prisma": "^5.16.2",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"zod": "^3.23.8"
},
"devDependencies": {
"@npc/cli": "workspace:^",
Expand All @@ -47,6 +48,7 @@
"@storybook/react": "8.2.4",
"@storybook/test": "8.2.4",
"@storybook/theming": "8.2.4",
"@svgr/webpack": "^8.1.0",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@types/lodash-es": "^4.17.12",
Expand Down
26 changes: 26 additions & 0 deletions apps/notes/prisma/migrations/20240722011911_072/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"clerkId" TEXT NOT NULL,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "Note" (
"id" TEXT NOT NULL,
"title" VARCHAR(255) NOT NULL,
"content" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"authorId" TEXT NOT NULL,
"color" TEXT NOT NULL,

CONSTRAINT "Note_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_clerkId_key" ON "User"("clerkId");

-- AddForeignKey
ALTER TABLE "Note" ADD CONSTRAINT "Note_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
3 changes: 3 additions & 0 deletions apps/notes/prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
49 changes: 0 additions & 49 deletions apps/notes/public/home.svg

This file was deleted.

9 changes: 0 additions & 9 deletions apps/notes/src/app/(auth)/layout.tsx

This file was deleted.

66 changes: 27 additions & 39 deletions apps/notes/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { IconInfo } from "@/assets/icon/info";
import { IconPlus } from "@/assets/icon/plus";
import { IconSearch } from "@/assets/icon/search";
import { ImageFirstNote } from "@/assets/image/first-note";
import { ButtonFixed } from "@/button/float";
import { ButtonIcon } from "@/button/icon";
import { prisma } from "@/prisma/client";
import { ButtonFixed } from "@libs/components/button/float";
import { ButtonIcon } from "@libs/components/button/icon";
import { NoteCardsRSC } from "@libs/components/card/rsc";
import { IconPlus } from "@libs/components/icon/plus";
import { IconSearch } from "@libs/components/icon/search";
import { ImageFirstNote } from "@libs/components/image/first-note";
import { InfoButton } from "@libs/components/info";
import { HeaderLayout } from "@libs/components/layout/header";
import { prisma } from "@libs/prisma/client";
import { IPageProps } from "@npc/shared/react-helpers";
import Link from "next/link";
import React from "react";
Expand All @@ -13,51 +15,37 @@ const Page: React.FC<IPageProps> = async (props) => {
const notes = await prisma.note.findMany();

return (
<div>
<header className="bg-primary flex items-center justify-between pb-9">
<h1 className="text-3xl font-semibold">Notes</h1>
<div className="flex gap-5">
<ButtonIcon>
<IconSearch alt="search" />
</ButtonIcon>
<div className="flex size-full flex-col">
<HeaderLayout
left={<h1 className="text-3xl font-semibold">Notes</h1>}
right={
<>
<Link href={"/search"}>
<ButtonIcon>
<IconSearch />
</ButtonIcon>
</Link>

<ButtonIcon>
<IconInfo alt="info" />
</ButtonIcon>
</div>
</header>
<InfoButton />
</>
}
/>

{notes.map(({ color, content, title, id }, index) => {
return (
<Link key={index} href={`/view/${id}`}>
<div
className="mb-7 rounded-md px-11 py-7 text-xl text-black"
style={{ background: color }}
>
{title}
</div>
</Link>
);
})}
<NoteCardsRSC notes={notes} />

{notes.length === 0 && (
<div
className="fixed inset-0 m-auto -mt-[10px] flex flex-col justify-center"
className="mt-[-10px] flex flex-1 flex-col justify-center"
hidden={notes.length > 0}
>
<ImageFirstNote
alt="background first note"
className="mx-auto"
height={286}
width={350}
/>
<ImageFirstNote className="mx-auto" height={286} width={350} />
<div className="text-center text-lg">Create your first note !</div>
</div>
)}

<Link className="fixed bottom-[60px] right-[46px]" href={"/add"}>
<ButtonFixed>
<IconPlus alt="add new note" size="xxl" />
<IconPlus />
</ButtonFixed>
</Link>
</div>
Expand Down
20 changes: 8 additions & 12 deletions apps/notes/src/app/add/page.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { actions } from "@/actions";
import { NoteEdit } from "@/note/edit";
import { ENoteEditMode } from "@/note/types";
import { prisma } from "@/prisma/client";
import { faker } from "@faker-js/faker";
import { actions } from "@libs/actions";
import { NoteEdit } from "@libs/components/edit/edit";
import { ENoteEditMode } from "@libs/components/edit/types";
import { INoteValidationInfer } from "@libs/components/edit/validation";
import { prisma } from "@libs/prisma/client";
import { IPageProps } from "@npc/shared/react-helpers";
import { redirect } from "next/navigation";
import React from "react";

const AddPage: React.FC<IPageProps> = async (props) => {
const save = async ({
title,
content,
}: {
title: string;
content: string;
}) => {
const save = async ({ title, content }: INoteValidationInfer) => {
"use server";
await prisma.note.create({
data: {
title,
content,
// TODO user pick a color
color: faker.color.rgb(),
author: {
connect: await actions.user.getCurrentOrThrow(),
Expand All @@ -30,7 +26,7 @@ const AddPage: React.FC<IPageProps> = async (props) => {
redirect("/");
};

return <NoteEdit defaultMode={ENoteEditMode.Edit} save={save} />;
return <NoteEdit actions={{ save }} defaultMode={ENoteEditMode.Edit} />;
};

export default AddPage;
2 changes: 1 addition & 1 deletion apps/notes/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

@import url("@npc/shared/styles.css");
@import url("@npc/theme/styles.css");
@import url("@/theme/variables.css");
@import url("@libs/theme/variables.css");

body,
html {
Expand Down
6 changes: 3 additions & 3 deletions apps/notes/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { actions } from "@/actions";
import { SyncElementClass } from "@/theme";
import { ClerkProvider } from "@clerk/nextjs";
import { dark } from "@clerk/themes";
import { actions } from "@libs/actions";
import { SyncElementClass } from "@libs/theme";
import { cn } from "@npc/shared/jsx";
import type { Metadata } from "next";
import { Nunito } from "next/font/google";
Expand Down Expand Up @@ -30,7 +30,7 @@ export default async function RootLayout({
<body
className={cn(
nunito.className,
"h-screen bg-primary text-primary px-6 py-12 overflow-y-auto",
"h-screen bg-primary text-primary px-6 py-12 overflow-y-auto flex flex-col justify-center items-center",
)}
>
{children}
Expand Down
48 changes: 48 additions & 0 deletions apps/notes/src/app/search/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { NoteCardsRSC } from "@libs/components/card/rsc";
import { ImageNotFound } from "@libs/components/image/not-found";
import { InputSearch } from "@libs/components/input/search";
import { HeaderLayout } from "@libs/components/layout/header";
import { prisma } from "@libs/prisma/client";
import { Back } from "@libs/router/back";
import { IPageProps } from "@npc/shared/react-helpers";
import React from "react";

const SearchPage: React.FC<IPageProps<{}, { q: string }>> = async (props) => {
const q = props.searchParams.q;
const notes = q
? await prisma.note.findMany({
where: {
title: {
contains: props.searchParams.q,
mode: "insensitive",
},
},
})
: [];

return (
<div className="flex size-full flex-col">
<HeaderLayout
left={<Back />}
right={<InputSearch className="w-full" searchParamKey="q" />}
rightClassName="flex-1 overflow-hidden"
/>

<NoteCardsRSC notes={notes} />

{notes.length === 0 && q && (
<div
className="mt-[-10px] flex flex-1 flex-col justify-center"
hidden={notes.length > 0}
>
<ImageNotFound className="mx-auto" height={286} width={350} />
<div className="text-center text-lg">
File not found. Try searching again.
</div>
</div>
)}
</div>
);
};

export default SearchPage;
Loading

0 comments on commit afa8b88

Please sign in to comment.