From 9b682c8af5ab3cd547a878e15d73e92c0bde226b Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 20 Oct 2023 17:12:08 +0100 Subject: [PATCH] vite * replace next with vite * disable strictmode (it interferes with collaboration in dev mode) --- client/.env.example | 2 + client/.eslintrc.cjs | 19 ++ client/.gitignore | 27 +++ client/README.md | 27 +++ client/index.html | 13 ++ {frontend => client}/package.json | 48 +++-- {frontend => client}/postcss.config.js | 0 client/public/vite.svg | 1 + client/src/App.tsx | 26 +++ client/src/assets/react.svg | 1 + client/src/components/layouts/layout.tsx | 14 ++ .../src/components/layouts}/shell.tsx | 3 - .../components/navbar/atoms/sidebar-atom.ts | 0 .../navbar/hooks/use-toggle-sidebar.ts | 0 .../src/components/navbar/navbar.module.css | 0 .../src/components/navbar/navbar.tsx | 8 +- .../components/navbar/user-button.module.css | 0 .../src/components/navbar/user-button.tsx | 2 - .../providers/tanstack-provider.tsx | 2 - .../src/components/theme-toggle.tsx | 2 - .../src/components/ui/custom-toaster.tsx | 4 +- .../features/auth/atoms/auth-tokens-atom.ts | 2 +- .../features/auth/components/login-form.tsx | 8 +- .../features/auth/components/sign-up-form.tsx | 10 +- .../src/features/auth/hooks/use-auth.ts | 8 +- .../features/auth/services/auth-service.ts | 0 .../src/features/auth/types/auth.types.ts | 0 client/src/features/editor/editor.tsx | 161 ++++++++++++++ .../editor/hooks/use-collaboration-url.ts | 6 +- client/src/features/editor/styles/editor.css | 199 ++++++++++++++++++ .../src/features/page/hooks/usePage.ts | 0 .../features/page/services/page-service.ts | 0 .../features/page/tree/atoms/tree-api-atom.ts | 0 .../page/tree/atoms/tree-data-atom.ts | 2 +- .../tree/atoms/workspace-page-order-atom.ts | 0 .../page/tree/components/fill-flex-parent.tsx | 5 +- .../page/tree/hooks/use-persistence.ts | 20 +- .../tree/hooks/use-workspace-page-order.ts | 0 .../src/features/page/tree/page-tree.tsx | 14 +- .../features/page/tree/styles/tree.module.css | 0 .../src/features/page/tree/types.ts | 0 .../src/features/page/types/page.types.ts | 0 .../src/features/search/search-spotlight.tsx | 0 .../account/settings/account-settings.tsx | 2 - .../settings/components/account-name-form.tsx | 2 - .../settings/components/change-email.tsx | 2 - .../settings/components/change-password.tsx | 2 - .../modal/atoms/settings-modal-atom.ts | 0 .../features/settings/modal/modal.module.css | 0 .../settings/modal/settings-modal.tsx | 2 - .../settings/modal/settings-sidebar.tsx | 2 - .../components/workspace-invite-form.tsx | 2 - .../components/workspace-invite-modal.tsx | 2 - .../components/workspace-invite-section.tsx | 2 - .../components/workspace-members-table.tsx | 2 - .../workspace/members/workspace-members.tsx | 2 - .../components/workspace-name-form.tsx | 2 - .../workspace/settings/workspace-settings.tsx | 2 - .../features/user/atoms/current-user-atom.ts | 0 .../features/user/hooks/use-current-user.ts | 0 .../features/user/services/user-service.ts | 0 .../src/features/user/types/user.types.ts | 0 .../src/features/user/user-provider.tsx | 2 - .../workspace/services/workspace-service.ts | 0 .../workspace/types/workspace.types.ts | 0 {frontend => client}/src/lib/api-client.ts | 2 +- {frontend => client}/src/lib/jotai-helper.ts | 0 {frontend => client}/src/lib/routes.ts | 0 client/src/main.tsx | 29 +++ .../src/pages/auth}/layout.tsx | 0 .../src/pages/auth/login.tsx | 2 - .../src/pages/auth/signup.tsx | 2 - .../src/pages/dashboard/home.tsx | 4 - client/src/pages/page/page.tsx | 8 + .../welcome => client/src/pages}/welcome.tsx | 2 +- {frontend/src/app => client/src}/theme.ts | 2 - client/src/vite-env.d.ts | 1 + client/tsconfig.json | 31 +++ client/tsconfig.node.json | 10 + client/vite.config.ts | 12 ++ frontend/.env.example | 2 - frontend/.eslintrc.json | 3 - frontend/.gitignore | 36 ---- frontend/README.md | 26 --- frontend/next.config.js | 4 - .../(dashboard)/(page)/p/[pageId]/page.tsx | 16 -- frontend/src/app/(dashboard)/layout.tsx | 21 -- frontend/src/app/favicon.ico | Bin 25931 -> 0 bytes frontend/src/app/layout.tsx | 41 ---- frontend/src/app/page.tsx | 6 - frontend/src/components/icons.tsx | 48 ----- frontend/src/features/editor/Editor.tsx | 110 ---------- .../src/features/editor/styles/editor.css | 26 --- .../page/tree/components/merge-refs.ts | 15 -- frontend/src/lib/utils.ts | 0 frontend/tsconfig.json | 29 --- 96 files changed, 645 insertions(+), 505 deletions(-) create mode 100644 client/.env.example create mode 100644 client/.eslintrc.cjs create mode 100644 client/.gitignore create mode 100644 client/README.md create mode 100644 client/index.html rename {frontend => client}/package.json (58%) rename {frontend => client}/postcss.config.js (100%) create mode 100644 client/public/vite.svg create mode 100644 client/src/App.tsx create mode 100644 client/src/assets/react.svg create mode 100644 client/src/components/layouts/layout.tsx rename {frontend/src/app/(dashboard) => client/src/components/layouts}/shell.tsx (98%) rename {frontend => client}/src/components/navbar/atoms/sidebar-atom.ts (100%) rename {frontend => client}/src/components/navbar/hooks/use-toggle-sidebar.ts (100%) rename {frontend => client}/src/components/navbar/navbar.module.css (100%) rename {frontend => client}/src/components/navbar/navbar.tsx (95%) rename {frontend => client}/src/components/navbar/user-button.module.css (100%) rename {frontend => client}/src/components/navbar/user-button.tsx (98%) rename {frontend => client}/src/components/providers/tanstack-provider.tsx (96%) rename {frontend => client}/src/components/theme-toggle.tsx (96%) rename {frontend => client}/src/components/ui/custom-toaster.tsx (96%) rename {frontend => client}/src/features/auth/atoms/auth-tokens-atom.ts (87%) rename {frontend => client}/src/features/auth/components/login-form.tsx (92%) rename {frontend => client}/src/features/auth/components/sign-up-form.tsx (94%) rename {frontend => client}/src/features/auth/hooks/use-auth.ts (91%) rename {frontend => client}/src/features/auth/services/auth-service.ts (100%) rename {frontend => client}/src/features/auth/types/auth.types.ts (100%) create mode 100644 client/src/features/editor/editor.tsx rename {frontend => client}/src/features/editor/hooks/use-collaboration-url.ts (65%) create mode 100644 client/src/features/editor/styles/editor.css rename {frontend => client}/src/features/page/hooks/usePage.ts (100%) rename {frontend => client}/src/features/page/services/page-service.ts (100%) rename {frontend => client}/src/features/page/tree/atoms/tree-api-atom.ts (100%) rename {frontend => client}/src/features/page/tree/atoms/tree-data-atom.ts (59%) rename {frontend => client}/src/features/page/tree/atoms/workspace-page-order-atom.ts (100%) rename {frontend => client}/src/features/page/tree/components/fill-flex-parent.tsx (79%) rename {frontend => client}/src/features/page/tree/hooks/use-persistence.ts (90%) rename {frontend => client}/src/features/page/tree/hooks/use-workspace-page-order.ts (100%) rename {frontend => client}/src/features/page/tree/page-tree.tsx (96%) rename {frontend => client}/src/features/page/tree/styles/tree.module.css (100%) rename {frontend => client}/src/features/page/tree/types.ts (100%) rename {frontend => client}/src/features/page/types/page.types.ts (100%) rename {frontend => client}/src/features/search/search-spotlight.tsx (100%) rename {frontend => client}/src/features/settings/account/settings/account-settings.tsx (97%) rename {frontend => client}/src/features/settings/account/settings/components/account-name-form.tsx (99%) rename {frontend => client}/src/features/settings/account/settings/components/change-email.tsx (99%) rename {frontend => client}/src/features/settings/account/settings/components/change-password.tsx (99%) rename {frontend => client}/src/features/settings/modal/atoms/settings-modal-atom.ts (100%) rename {frontend => client}/src/features/settings/modal/modal.module.css (100%) rename {frontend => client}/src/features/settings/modal/settings-modal.tsx (98%) rename {frontend => client}/src/features/settings/modal/settings-sidebar.tsx (99%) rename {frontend => client}/src/features/settings/workspace/members/components/workspace-invite-form.tsx (98%) rename {frontend => client}/src/features/settings/workspace/members/components/workspace-invite-modal.tsx (98%) rename {frontend => client}/src/features/settings/workspace/members/components/workspace-invite-section.tsx (98%) rename {frontend => client}/src/features/settings/workspace/members/components/workspace-members-table.tsx (99%) rename {frontend => client}/src/features/settings/workspace/members/workspace-members.tsx (98%) rename {frontend => client}/src/features/settings/workspace/settings/components/workspace-name-form.tsx (99%) rename {frontend => client}/src/features/settings/workspace/settings/workspace-settings.tsx (92%) rename {frontend => client}/src/features/user/atoms/current-user-atom.ts (100%) rename {frontend => client}/src/features/user/hooks/use-current-user.ts (100%) rename {frontend => client}/src/features/user/services/user-service.ts (100%) rename {frontend => client}/src/features/user/types/user.types.ts (100%) rename {frontend => client}/src/features/user/user-provider.tsx (97%) rename {frontend => client}/src/features/workspace/services/workspace-service.ts (100%) rename {frontend => client}/src/features/workspace/types/workspace.types.ts (100%) rename {frontend => client}/src/lib/api-client.ts (95%) rename {frontend => client}/src/lib/jotai-helper.ts (100%) rename {frontend => client}/src/lib/routes.ts (100%) create mode 100644 client/src/main.tsx rename {frontend/src/app/(auth) => client/src/pages/auth}/layout.tsx (100%) rename frontend/src/app/(auth)/login/page.tsx => client/src/pages/auth/login.tsx (89%) rename frontend/src/app/(auth)/signup/page.tsx => client/src/pages/auth/signup.tsx (90%) rename frontend/src/app/(dashboard)/home/page.tsx => client/src/pages/dashboard/home.tsx (80%) create mode 100644 client/src/pages/page/page.tsx rename {frontend/src/components/welcome => client/src/pages}/welcome.tsx (89%) rename {frontend/src/app => client/src}/theme.ts (85%) create mode 100644 client/src/vite-env.d.ts create mode 100644 client/tsconfig.json create mode 100644 client/tsconfig.node.json create mode 100644 client/vite.config.ts delete mode 100644 frontend/.env.example delete mode 100644 frontend/.eslintrc.json delete mode 100644 frontend/.gitignore delete mode 100644 frontend/README.md delete mode 100644 frontend/next.config.js delete mode 100644 frontend/src/app/(dashboard)/(page)/p/[pageId]/page.tsx delete mode 100644 frontend/src/app/(dashboard)/layout.tsx delete mode 100644 frontend/src/app/favicon.ico delete mode 100644 frontend/src/app/layout.tsx delete mode 100644 frontend/src/app/page.tsx delete mode 100644 frontend/src/components/icons.tsx delete mode 100644 frontend/src/features/editor/Editor.tsx delete mode 100644 frontend/src/features/editor/styles/editor.css delete mode 100644 frontend/src/features/page/tree/components/merge-refs.ts delete mode 100644 frontend/src/lib/utils.ts delete mode 100644 frontend/tsconfig.json diff --git a/client/.env.example b/client/.env.example new file mode 100644 index 00000000..e4a40632 --- /dev/null +++ b/client/.env.example @@ -0,0 +1,2 @@ +VITE_BACKEND_API_URL=http://localhost:3001 +VITE_COLLABORATION_URL= diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs new file mode 100644 index 00000000..bb62692d --- /dev/null +++ b/client/.eslintrc.cjs @@ -0,0 +1,19 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + '@typescript-eslint/no-explicit-any': 'off', + }, +} diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 00000000..44139841 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,27 @@ +.env +package-lock.json + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/client/README.md b/client/README.md new file mode 100644 index 00000000..1ebe379f --- /dev/null +++ b/client/README.md @@ -0,0 +1,27 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: __dirname, + }, +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/client/index.html b/client/index.html new file mode 100644 index 00000000..e4b78eae --- /dev/null +++ b/client/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/frontend/package.json b/client/package.json similarity index 58% rename from frontend/package.json rename to client/package.json index c997fb5c..9e245c82 100644 --- a/frontend/package.json +++ b/client/package.json @@ -1,21 +1,20 @@ { - "name": "frontend", - "version": "0.1.0", + "name": "client", "private": true, + "version": "0.0.0", "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "prebuild": "next telemetry disable", - "lint": "next lint" + "dev": "vite --port 3000", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview --port 3000" }, "dependencies": { "@hocuspocus/provider": "^2.7.0", - "@mantine/core": "^7.1.3", - "@mantine/form": "^7.1.3", - "@mantine/hooks": "^7.1.3", - "@mantine/spotlight": "^7.1.3", - "@mantine/tiptap": "^7.1.3", + "@mantine/core": "^7.1.5", + "@mantine/form": "^7.1.5", + "@mantine/hooks": "^7.1.5", + "@mantine/spotlight": "^7.1.5", + "@mantine/tiptap": "^7.1.5", "@tabler/icons-react": "^2.39.0", "@tanstack/react-query": "^4.36.1", "@tanstack/react-table": "^8.10.7", @@ -38,13 +37,12 @@ "jotai": "^2.4.3", "jotai-optics": "^0.3.1", "js-cookie": "^3.0.5", - "next": "13.5.5", - "react": "18.2.0", + "react": "^18.2.0", "react-arborist": "^3.2.0", - "react-dom": "18.2.0", + "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", + "react-router-dom": "^6.17.0", "socket.io-client": "^4.7.2", - "typescript": "5.2.2", "uuid": "^9.0.1", "y-indexeddb": "^9.0.11", "yjs": "^13.6.8", @@ -53,13 +51,21 @@ "devDependencies": { "@types/js-cookie": "^3.0.4", "@types/node": "20.8.6", - "@types/react": "18.2.28", - "@types/react-dom": "18.2.13", - "eslint": "8.51.0", - "eslint-config-next": "13.5.5", + "@types/react": "^18.2.29", + "@types/react-dom": "^18.2.14", + "@types/uuid": "^9.0.6", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-react": "^4.0.3", + "eslint": "^8.51.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", "optics-ts": "^2.4.1", "postcss": "^8.4.31", "postcss-preset-mantine": "^1.9.0", - "postcss-simple-vars": "^7.0.1" + "postcss-simple-vars": "^7.0.1", + "prettier": "^3.0.3", + "typescript": "^5.2.2", + "vite": "^4.4.5" } } diff --git a/frontend/postcss.config.js b/client/postcss.config.js similarity index 100% rename from frontend/postcss.config.js rename to client/postcss.config.js diff --git a/client/public/vite.svg b/client/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/client/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 00000000..13d342e7 --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,26 @@ +import { Route, Routes } from 'react-router-dom'; +import { Welcome } from '@/pages/welcome'; +import SignUpPage from '@/pages/auth/signup'; +import LoginPage from '@/pages/auth/login'; +import DashboardLayout from '@/components/layouts/layout'; +import Home from '@/pages/dashboard/home'; +import Page from '@/pages/page/page'; + +export default function App() { + + return ( + <> + + } /> + } /> + } /> + + }> + } /> + } /> + + + + + ); +} diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/client/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/components/layouts/layout.tsx b/client/src/components/layouts/layout.tsx new file mode 100644 index 00000000..ed953ea6 --- /dev/null +++ b/client/src/components/layouts/layout.tsx @@ -0,0 +1,14 @@ +import { UserProvider } from '@/features/user/user-provider'; +import Shell from './shell'; +import { Outlet } from 'react-router-dom'; + +export default function DashboardLayout() { + + return ( + + + + + + ); +} diff --git a/frontend/src/app/(dashboard)/shell.tsx b/client/src/components/layouts/shell.tsx similarity index 98% rename from frontend/src/app/(dashboard)/shell.tsx rename to client/src/components/layouts/shell.tsx index 14049196..88bc30a6 100644 --- a/frontend/src/app/(dashboard)/shell.tsx +++ b/client/src/components/layouts/shell.tsx @@ -1,5 +1,3 @@ -'use client'; - import { desktopSidebarAtom } from '@/components/navbar/atoms/sidebar-atom'; import { useToggleSidebar } from '@/components/navbar/hooks/use-toggle-sidebar'; import { Navbar } from '@/components/navbar/navbar'; @@ -12,7 +10,6 @@ export default function Shell({ children }: { children: React.ReactNode }) { const [desktopOpened] = useAtom(desktopSidebarAtom); const toggleDesktop = useToggleSidebar(desktopSidebarAtom); - return ( import("@/features/page/tree/page-tree"), { - ssr: false, -}); +import PageTree from '@/features/page/tree/page-tree'; interface PrimaryMenuItem { icon: React.ElementType; diff --git a/frontend/src/components/navbar/user-button.module.css b/client/src/components/navbar/user-button.module.css similarity index 100% rename from frontend/src/components/navbar/user-button.module.css rename to client/src/components/navbar/user-button.module.css diff --git a/frontend/src/components/navbar/user-button.tsx b/client/src/components/navbar/user-button.tsx similarity index 98% rename from frontend/src/components/navbar/user-button.tsx rename to client/src/components/navbar/user-button.tsx index 0a13d1da..1785148b 100644 --- a/frontend/src/components/navbar/user-button.tsx +++ b/client/src/components/navbar/user-button.tsx @@ -1,5 +1,3 @@ -'use client'; - import { UnstyledButton, Group, Avatar, Text, rem } from '@mantine/core'; import { IconChevronRight } from '@tabler/icons-react'; import classes from './user-button.module.css'; diff --git a/frontend/src/components/providers/tanstack-provider.tsx b/client/src/components/providers/tanstack-provider.tsx similarity index 96% rename from frontend/src/components/providers/tanstack-provider.tsx rename to client/src/components/providers/tanstack-provider.tsx index 9a4a1724..c4e9c773 100644 --- a/frontend/src/components/providers/tanstack-provider.tsx +++ b/client/src/components/providers/tanstack-provider.tsx @@ -1,5 +1,3 @@ -'use client'; - import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import React from 'react'; diff --git a/frontend/src/components/theme-toggle.tsx b/client/src/components/theme-toggle.tsx similarity index 96% rename from frontend/src/components/theme-toggle.tsx rename to client/src/components/theme-toggle.tsx index 1b803eaa..a988db6f 100644 --- a/frontend/src/components/theme-toggle.tsx +++ b/client/src/components/theme-toggle.tsx @@ -1,5 +1,3 @@ -'use client'; - import { Button, Group, useMantineColorScheme } from '@mantine/core'; export function ThemeToggle() { diff --git a/frontend/src/components/ui/custom-toaster.tsx b/client/src/components/ui/custom-toaster.tsx similarity index 96% rename from frontend/src/components/ui/custom-toaster.tsx rename to client/src/components/ui/custom-toaster.tsx index 2b487f03..657eaf4f 100644 --- a/frontend/src/components/ui/custom-toaster.tsx +++ b/client/src/components/ui/custom-toaster.tsx @@ -1,5 +1,3 @@ -"use client"; - import t, { Toaster, useToasterStore } from "react-hot-toast"; import { useEffect, useState } from "react"; @@ -18,4 +16,4 @@ export default function CustomToaster() { }, [toastLimit, toasts]); return ; -}; +} diff --git a/frontend/src/features/auth/atoms/auth-tokens-atom.ts b/client/src/features/auth/atoms/auth-tokens-atom.ts similarity index 87% rename from frontend/src/features/auth/atoms/auth-tokens-atom.ts rename to client/src/features/auth/atoms/auth-tokens-atom.ts index 4cd7d035..7088d2a3 100644 --- a/frontend/src/features/auth/atoms/auth-tokens-atom.ts +++ b/client/src/features/auth/atoms/auth-tokens-atom.ts @@ -1,6 +1,6 @@ import Cookies from "js-cookie"; import { createJSONStorage, atomWithStorage } from "jotai/utils"; -import { ITokens } from "@/features/auth/types/auth.types"; +import { ITokens } from '../types/auth.types'; const cookieStorage = createJSONStorage(() => { diff --git a/frontend/src/features/auth/components/login-form.tsx b/client/src/features/auth/components/login-form.tsx similarity index 92% rename from frontend/src/features/auth/components/login-form.tsx rename to client/src/features/auth/components/login-form.tsx index 52dec318..a8498121 100644 --- a/frontend/src/features/auth/components/login-form.tsx +++ b/client/src/features/auth/components/login-form.tsx @@ -1,5 +1,3 @@ -'use client'; - import * as React from 'react'; import * as z from 'zod'; @@ -16,7 +14,7 @@ import { Text, PasswordInput, } from '@mantine/core'; -import Link from 'next/link'; +import { Link } from 'react-router-dom'; const formSchema = z.object({ email: z @@ -46,8 +44,8 @@ export function LoginForm() { Login - Do not have an account yet?{' '} - + Don't have an account yet?{' '} + Create account diff --git a/frontend/src/features/auth/components/sign-up-form.tsx b/client/src/features/auth/components/sign-up-form.tsx similarity index 94% rename from frontend/src/features/auth/components/sign-up-form.tsx rename to client/src/features/auth/components/sign-up-form.tsx index cb0718f0..05f4764c 100644 --- a/frontend/src/features/auth/components/sign-up-form.tsx +++ b/client/src/features/auth/components/sign-up-form.tsx @@ -1,11 +1,7 @@ -'use client'; - import * as React from 'react'; import * as z from 'zod'; import { useForm, zodResolver } from '@mantine/form'; -import useAuth from '@/features/auth/hooks/use-auth'; -import { IRegister } from '@/features/auth/types/auth.types'; import { Container, Title, @@ -16,7 +12,9 @@ import { Text, PasswordInput, } from '@mantine/core'; -import Link from 'next/link'; +import { Link } from 'react-router-dom'; +import { IRegister } from '@/features/auth/types/auth.types'; +import useAuth from '@/features/auth/hooks/use-auth'; const formSchema = z.object({ email: z @@ -47,7 +45,7 @@ export function SignUpForm() { Already have an account?{' '} - + Login diff --git a/frontend/src/features/auth/hooks/use-auth.ts b/client/src/features/auth/hooks/use-auth.ts similarity index 91% rename from frontend/src/features/auth/hooks/use-auth.ts rename to client/src/features/auth/hooks/use-auth.ts index 38ca33f2..980f6a31 100644 --- a/frontend/src/features/auth/hooks/use-auth.ts +++ b/client/src/features/auth/hooks/use-auth.ts @@ -1,6 +1,6 @@ import { useState } from "react"; import { login, register } from "@/features/auth/services/auth-service"; -import { useRouter } from "next/navigation"; +import { useNavigate } from "react-router-dom"; import { useAtom } from "jotai"; import { authTokensAtom } from "@/features/auth/atoms/auth-tokens-atom"; import { currentUserAtom } from "@/features/user/atoms/current-user-atom"; @@ -9,7 +9,7 @@ import toast from "react-hot-toast"; export default function useAuth() { const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); + const navigate = useNavigate(); const [, setCurrentUser] = useAtom(currentUserAtom); const [authToken, setAuthToken] = useAtom(authTokensAtom); @@ -22,7 +22,7 @@ export default function useAuth() { setIsLoading(false); setAuthToken(res.tokens); - router.push("/home"); + navigate("/home"); } catch (err) { setIsLoading(false); toast.error(err.response?.data.message) @@ -38,7 +38,7 @@ export default function useAuth() { setAuthToken(res.tokens); - router.push("/home"); + navigate("/home"); } catch (err) { setIsLoading(false); toast.error(err.response?.data.message) diff --git a/frontend/src/features/auth/services/auth-service.ts b/client/src/features/auth/services/auth-service.ts similarity index 100% rename from frontend/src/features/auth/services/auth-service.ts rename to client/src/features/auth/services/auth-service.ts diff --git a/frontend/src/features/auth/types/auth.types.ts b/client/src/features/auth/types/auth.types.ts similarity index 100% rename from frontend/src/features/auth/types/auth.types.ts rename to client/src/features/auth/types/auth.types.ts diff --git a/client/src/features/editor/editor.tsx b/client/src/features/editor/editor.tsx new file mode 100644 index 00000000..c27ea681 --- /dev/null +++ b/client/src/features/editor/editor.tsx @@ -0,0 +1,161 @@ +import '@/features/editor/styles/editor.css'; + +import { HocuspocusProvider } from '@hocuspocus/provider'; +import * as Y from 'yjs'; +import { EditorContent, useEditor } from '@tiptap/react'; +import { StarterKit } from '@tiptap/starter-kit'; +import { Placeholder } from '@tiptap/extension-placeholder'; +import { Collaboration } from '@tiptap/extension-collaboration'; +import { CollaborationCursor } from '@tiptap/extension-collaboration-cursor'; +import { useEffect, useLayoutEffect, useState } from 'react'; +import { useAtom } from 'jotai'; +import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; +import { authTokensAtom } from '@/features/auth/atoms/auth-tokens-atom'; +import useCollaborationUrl from '@/features/editor/hooks/use-collaboration-url'; +import { IndexeddbPersistence } from 'y-indexeddb'; +import { RichTextEditor } from '@mantine/tiptap'; +import { TextAlign } from '@tiptap/extension-text-align'; +import { Highlight } from '@tiptap/extension-highlight'; +import { Superscript } from '@tiptap/extension-superscript'; +import SubScript from '@tiptap/extension-subscript'; +import { Link } from '@tiptap/extension-link'; +import { Underline } from '@tiptap/extension-underline'; + +interface EditorProps { + pageId: string, + token?: string, +} + +const colors = ['#958DF1', '#F98181', '#FBBC88', '#FAF594', '#70CFF8', '#94FADB', '#B9F18D']; +const getRandomElement = list => list[Math.floor(Math.random() * list.length)]; +const getRandomColor = () => getRandomElement(colors); + +export default function Editor({ pageId }: EditorProps) { + const [token] = useAtom(authTokensAtom); + const collaborationURL = useCollaborationUrl(); + const [provider, setProvider] = useState(); + const [yDoc] = useState(() => new Y.Doc()); + + + useEffect(() => { + if (token) { + const indexeddbProvider = new IndexeddbPersistence(pageId, yDoc) + const provider = new HocuspocusProvider({ + url: collaborationURL, + name: pageId, + document: yDoc, + token: token.accessToken, + }); + + setProvider(provider); + + return () => { + provider.destroy(); + setProvider(null); + indexeddbProvider.destroy(); + }; + } + }, [pageId, token]); + + if (!provider) { + return null; + } + + return ( + + ); +} + +interface TiptapEditorProps { + ydoc: Y.Doc, + provider: HocuspocusProvider +} + +function TiptapEditor({ ydoc, provider }: TiptapEditorProps) { + const [currentUser] = useAtom(currentUserAtom); + + const extensions = [ + StarterKit.configure({ + history: false, + }), + Placeholder.configure({ + placeholder: 'Write here', + }), + Collaboration.configure({ + document: ydoc, + }), + CollaborationCursor.configure({ + provider, + }), + Underline, + Link, + Superscript, + SubScript, + Highlight, + TextAlign.configure({ types: ['heading', 'paragraph'] }), + ]; + + const editor = useEditor({ + extensions: extensions, + }); + + useEffect(() => { + if (editor && currentUser.user) { + editor.chain().focus().updateUser({ ...currentUser.user, color: getRandomColor() }).run(); + } + }, [editor, currentUser.user]); + + useEffect(() => { + provider.on('status', event => { + console.log(event); + }); + + }, [provider]); + + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/frontend/src/features/editor/hooks/use-collaboration-url.ts b/client/src/features/editor/hooks/use-collaboration-url.ts similarity index 65% rename from frontend/src/features/editor/hooks/use-collaboration-url.ts rename to client/src/features/editor/hooks/use-collaboration-url.ts index 16f65549..5741becd 100644 --- a/frontend/src/features/editor/hooks/use-collaboration-url.ts +++ b/client/src/features/editor/hooks/use-collaboration-url.ts @@ -1,11 +1,11 @@ const useCollaborationURL = (): string => { const PATH = "/collaboration"; - if (process.env.NEXT_PUBLIC_COLLABORATION_URL) { - return process.env.NEXT_PUBLIC_COLLABORATION_URL + PATH; + if (import.meta.env.VITE_COLLABORATION_URL) { + return import.meta.env.VITE_COLLABORATION_URL + PATH; } - const API_URL = process.env.NEXT_PUBLIC_BACKEND_API_URL; + const API_URL = import.meta.env.VITE_BACKEND_API_URL; if (!API_URL) { throw new Error("Backend API URL is not defined"); } diff --git a/client/src/features/editor/styles/editor.css b/client/src/features/editor/styles/editor.css new file mode 100644 index 00000000..7cf3608e --- /dev/null +++ b/client/src/features/editor/styles/editor.css @@ -0,0 +1,199 @@ +/* Basic editor styles */ +.tiptap { + > * + * { + margin-top: 0.75em; + } + + ul, + ol { + padding: 0 1rem; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + } + + code { + background-color: rgba(#616161, 0.1); + color: #616161; + } + + pre { + background: #0d0d0d; + border-radius: 0.5rem; + color: #fff; + font-family: "JetBrainsMono", monospace; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + mark { + background-color: #faf594; + } + + img { + height: auto; + max-width: 100%; + } + + hr { + margin: 1rem 0; + } + + blockquote { + border-left: 2px solid rgba(#0d0d0d, 0.1); + padding-left: 1rem; + } + + hr { + border: none; + border-top: 2px solid rgba(#0d0d0d, 0.1); + margin: 2rem 0; + } + + ul[data-type="taskList"] { + list-style: none; + padding: 0; + + li { + align-items: center; + display: flex; + + > label { + flex: 0 0 auto; + margin-right: 0.5rem; + user-select: none; + } + + > div { + flex: 1 1 auto; + } + } + } +} + +.editor { + background-color: #fff; + border: 2px solid #0d0d0d; + border-radius: 0.75rem; + box-shadow: 5px 5px #000; + color: #0d0d0d; + display: flex; + flex-direction: column; + max-height: 26rem; + + &__header { + align-items: center; + border-bottom: 2px solid #0d0d0d; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + display: flex; + justify-content: space-between; + padding: 0.5rem 1rem; + } + + &__users { + color: rgba(#000, 0.8); + display: flex; + font-size: 0.85rem; + gap: 1rem; + } + + &__content { + flex: 1 1 auto; + overflow-x: hidden; + overflow-y: auto; + padding: 1.25rem 1rem; + -webkit-overflow-scrolling: touch; + } + + /* Some information about the status */ + &__status { + align-items: center; + border-radius: 5px; + display: flex; + + &::before { + background: rgba(#0d0d0d, 0.5); + border-radius: 50%; + content: " "; + display: inline-block; + flex: 0 0 auto; + height: 0.5rem; + margin-right: 0.5rem; + width: 0.5rem; + } + + &--connecting::before { + background: #616161; + } + + &--connected::before { + background: #b9f18d; + } + } + + &__name button { + appearance: none; + background: transparent; + border: none; + color: inherit; + cursor: pointer; + font: inherit; + line-height: normal; + margin: 0; + padding: 0; + overflow: visible; + width: auto; + } +} + +/* Give a remote user a caret */ +.collaboration-cursor__caret { + border-left: 1px solid #0d0d0d; + border-right: 1px solid #0d0d0d; + margin-left: -1px; + margin-right: -1px; + pointer-events: none; + position: relative; + word-break: normal; +} + +/* Render the username above the caret */ +.collaboration-cursor__label { + border-radius: 3px 3px 3px 0; + color: #0d0d0d; + font-size: 0.75rem; + font-style: normal; + font-weight: 600; + left: -1px; + line-height: normal; + padding: 0.1rem 0.3rem; + position: absolute; + top: -1.4em; + user-select: none; + white-space: nowrap; +} + +.dots { + display: flex; + gap: 6px; +} + +.dot { + background: #000; + border-radius: 100%; + height: 0.625rem; + width: 0.625rem; +} diff --git a/frontend/src/features/page/hooks/usePage.ts b/client/src/features/page/hooks/usePage.ts similarity index 100% rename from frontend/src/features/page/hooks/usePage.ts rename to client/src/features/page/hooks/usePage.ts diff --git a/frontend/src/features/page/services/page-service.ts b/client/src/features/page/services/page-service.ts similarity index 100% rename from frontend/src/features/page/services/page-service.ts rename to client/src/features/page/services/page-service.ts diff --git a/frontend/src/features/page/tree/atoms/tree-api-atom.ts b/client/src/features/page/tree/atoms/tree-api-atom.ts similarity index 100% rename from frontend/src/features/page/tree/atoms/tree-api-atom.ts rename to client/src/features/page/tree/atoms/tree-api-atom.ts diff --git a/frontend/src/features/page/tree/atoms/tree-data-atom.ts b/client/src/features/page/tree/atoms/tree-data-atom.ts similarity index 59% rename from frontend/src/features/page/tree/atoms/tree-data-atom.ts rename to client/src/features/page/tree/atoms/tree-data-atom.ts index 5ce297a8..3d4c67f6 100644 --- a/frontend/src/features/page/tree/atoms/tree-data-atom.ts +++ b/client/src/features/page/tree/atoms/tree-data-atom.ts @@ -1,4 +1,4 @@ import { atom } from "jotai"; -import { TreeNode } from "../types"; +import { TreeNode } from '@/features/page/tree/types'; export const treeDataAtom = atom([]); diff --git a/frontend/src/features/page/tree/atoms/workspace-page-order-atom.ts b/client/src/features/page/tree/atoms/workspace-page-order-atom.ts similarity index 100% rename from frontend/src/features/page/tree/atoms/workspace-page-order-atom.ts rename to client/src/features/page/tree/atoms/workspace-page-order-atom.ts diff --git a/frontend/src/features/page/tree/components/fill-flex-parent.tsx b/client/src/features/page/tree/components/fill-flex-parent.tsx similarity index 79% rename from frontend/src/features/page/tree/components/fill-flex-parent.tsx rename to client/src/features/page/tree/components/fill-flex-parent.tsx index 7d88a6be..df1a4f8b 100644 --- a/frontend/src/features/page/tree/components/fill-flex-parent.tsx +++ b/client/src/features/page/tree/components/fill-flex-parent.tsx @@ -1,6 +1,6 @@ import React, { ReactElement } from 'react'; -import mergeRefs from './merge-refs'; import { useElementSize } from '@mantine/hooks'; +import { useMergedRef } from '@mantine/hooks'; type Props = { children: (dimens: { width: number; height: number }) => ReactElement; @@ -19,8 +19,9 @@ export const FillFlexParent = React.forwardRef(function FillFlexParent( forwardRef ) { const { ref, width, height } = useElementSize(); + const mergedRef = useMergedRef(ref, forwardRef); return ( -
+
{width && height ? props.children({ width, height }) : null}
); diff --git a/frontend/src/features/page/tree/hooks/use-persistence.ts b/client/src/features/page/tree/hooks/use-persistence.ts similarity index 90% rename from frontend/src/features/page/tree/hooks/use-persistence.ts rename to client/src/features/page/tree/hooks/use-persistence.ts index 5c4c77c2..4591fc16 100644 --- a/frontend/src/features/page/tree/hooks/use-persistence.ts +++ b/client/src/features/page/tree/hooks/use-persistence.ts @@ -1,5 +1,3 @@ -'use client' - import { useMemo } from 'react'; import { CreateHandler, @@ -13,18 +11,16 @@ import { treeDataAtom } from '@/features/page/tree/atoms/tree-data-atom'; import { createPage, deletePage, movePage, updatePage } from '@/features/page/services/page-service'; import { v4 as uuidv4 } from 'uuid'; import { IMovePage } from '@/features/page/types/page.types'; -import { useRouter } from 'next/navigation'; +import { useNavigate} from 'react-router-dom'; +import { TreeNode } from '@/features/page/tree/types'; + export function usePersistence() { - const [data, setData] = useAtom(treeDataAtom); - const router = useRouter(); + const [data, setData] = useAtom(treeDataAtom); + const navigate = useNavigate(); + + const tree = useMemo(() => new SimpleTree(data), [data]); - const tree = useMemo( - () => - new SimpleTree(data), - [data], - ); const onMove: MoveHandler = (args: { parentId, index, parentNode, dragNodes, dragIds }) => { for (const id of args.dragIds) { @@ -80,7 +76,7 @@ export function usePersistence() { try { await createPage(payload); - router.push(`/p/${payload.id}`); + navigate(`/p/${payload.id}`); } catch (error) { console.error('Error creating the page:', error); } diff --git a/frontend/src/features/page/tree/hooks/use-workspace-page-order.ts b/client/src/features/page/tree/hooks/use-workspace-page-order.ts similarity index 100% rename from frontend/src/features/page/tree/hooks/use-workspace-page-order.ts rename to client/src/features/page/tree/hooks/use-workspace-page-order.ts diff --git a/frontend/src/features/page/tree/page-tree.tsx b/client/src/features/page/tree/page-tree.tsx similarity index 96% rename from frontend/src/features/page/tree/page-tree.tsx rename to client/src/features/page/tree/page-tree.tsx index f6e9a37a..c055558f 100644 --- a/frontend/src/features/page/tree/page-tree.tsx +++ b/client/src/features/page/tree/page-tree.tsx @@ -1,5 +1,3 @@ -'use client'; - import { NodeApi, NodeRendererProps, Tree, TreeApi } from 'react-arborist'; import { IconArrowsLeftRight, @@ -28,13 +26,13 @@ import { usePersistence } from '@/features/page/tree/hooks/use-persistence'; import { IPage } from '@/features/page/types/page.types'; import { getPages } from '@/features/page/services/page-service'; import useWorkspacePageOrder from '@/features/page/tree/hooks/use-workspace-page-order'; -import { usePathname, useRouter } from 'next/navigation'; +import { useLocation, useNavigate} from 'react-router-dom'; export default function PageTree() { const { data, setData, controllers } = usePersistence>(); const [tree, setTree] = useAtom>(treeApiAtom); const { data: pageOrderData } = useWorkspacePageOrder(); - const pathname = usePathname(); + const location = useLocation(); const fetchAndSetTreeData = async () => { if (pageOrderData?.childrenIds) { @@ -53,11 +51,11 @@ export default function PageTree() { }, [pageOrderData?.childrenIds]); useEffect(() => { - const pageId = pathname?.split('/')[2]; + const pageId = location.pathname.split('/')[2]; setTimeout(() => { tree?.select(pageId); }, 100); - }, [tree, pathname]); + }, [tree, location.pathname]); return (
@@ -86,10 +84,10 @@ export default function PageTree() { } function Node({ node, style, dragHandle }: NodeRendererProps) { - const router = useRouter(); + const navigate = useNavigate(); const handleClick = () => { - router.push(`/p/${node.id}`); + navigate(`/p/${node.id}`); } if (node.willReceiveDrop && node.isClosed){ diff --git a/frontend/src/features/page/tree/styles/tree.module.css b/client/src/features/page/tree/styles/tree.module.css similarity index 100% rename from frontend/src/features/page/tree/styles/tree.module.css rename to client/src/features/page/tree/styles/tree.module.css diff --git a/frontend/src/features/page/tree/types.ts b/client/src/features/page/tree/types.ts similarity index 100% rename from frontend/src/features/page/tree/types.ts rename to client/src/features/page/tree/types.ts diff --git a/frontend/src/features/page/types/page.types.ts b/client/src/features/page/types/page.types.ts similarity index 100% rename from frontend/src/features/page/types/page.types.ts rename to client/src/features/page/types/page.types.ts diff --git a/frontend/src/features/search/search-spotlight.tsx b/client/src/features/search/search-spotlight.tsx similarity index 100% rename from frontend/src/features/search/search-spotlight.tsx rename to client/src/features/search/search-spotlight.tsx diff --git a/frontend/src/features/settings/account/settings/account-settings.tsx b/client/src/features/settings/account/settings/account-settings.tsx similarity index 97% rename from frontend/src/features/settings/account/settings/account-settings.tsx rename to client/src/features/settings/account/settings/account-settings.tsx index a40899a4..f10b742e 100644 --- a/frontend/src/features/settings/account/settings/account-settings.tsx +++ b/client/src/features/settings/account/settings/account-settings.tsx @@ -1,5 +1,3 @@ -'use client'; - import React from "react"; import AccountNameForm from '@/features/settings/account/settings/components/account-name-form'; import ChangeEmail from '@/features/settings/account/settings/components/change-email'; diff --git a/frontend/src/features/settings/account/settings/components/account-name-form.tsx b/client/src/features/settings/account/settings/components/account-name-form.tsx similarity index 99% rename from frontend/src/features/settings/account/settings/components/account-name-form.tsx rename to client/src/features/settings/account/settings/components/account-name-form.tsx index bce4b09b..f92c6448 100644 --- a/frontend/src/features/settings/account/settings/components/account-name-form.tsx +++ b/client/src/features/settings/account/settings/components/account-name-form.tsx @@ -1,5 +1,3 @@ -'use client'; - import { useAtom } from 'jotai'; import { focusAtom } from 'jotai-optics'; import * as z from 'zod'; diff --git a/frontend/src/features/settings/account/settings/components/change-email.tsx b/client/src/features/settings/account/settings/components/change-email.tsx similarity index 99% rename from frontend/src/features/settings/account/settings/components/change-email.tsx rename to client/src/features/settings/account/settings/components/change-email.tsx index 3be78c31..e10d481f 100644 --- a/frontend/src/features/settings/account/settings/components/change-email.tsx +++ b/client/src/features/settings/account/settings/components/change-email.tsx @@ -1,5 +1,3 @@ -'use client'; - import { Modal, TextInput, Button, Text, Group, PasswordInput } from '@mantine/core'; import * as z from 'zod'; import { useState } from 'react'; diff --git a/frontend/src/features/settings/account/settings/components/change-password.tsx b/client/src/features/settings/account/settings/components/change-password.tsx similarity index 99% rename from frontend/src/features/settings/account/settings/components/change-password.tsx rename to client/src/features/settings/account/settings/components/change-password.tsx index 2d832824..3272f42f 100644 --- a/frontend/src/features/settings/account/settings/components/change-password.tsx +++ b/client/src/features/settings/account/settings/components/change-password.tsx @@ -1,5 +1,3 @@ -'use client'; - import { Button, Group, Text, Modal, PasswordInput } from '@mantine/core'; import * as z from 'zod'; import { useState } from 'react'; diff --git a/frontend/src/features/settings/modal/atoms/settings-modal-atom.ts b/client/src/features/settings/modal/atoms/settings-modal-atom.ts similarity index 100% rename from frontend/src/features/settings/modal/atoms/settings-modal-atom.ts rename to client/src/features/settings/modal/atoms/settings-modal-atom.ts diff --git a/frontend/src/features/settings/modal/modal.module.css b/client/src/features/settings/modal/modal.module.css similarity index 100% rename from frontend/src/features/settings/modal/modal.module.css rename to client/src/features/settings/modal/modal.module.css diff --git a/frontend/src/features/settings/modal/settings-modal.tsx b/client/src/features/settings/modal/settings-modal.tsx similarity index 98% rename from frontend/src/features/settings/modal/settings-modal.tsx rename to client/src/features/settings/modal/settings-modal.tsx index 44288686..9fb4448f 100644 --- a/frontend/src/features/settings/modal/settings-modal.tsx +++ b/client/src/features/settings/modal/settings-modal.tsx @@ -1,5 +1,3 @@ -'use client'; - import { Modal, Text } from '@mantine/core'; import React from 'react'; import SettingsSidebar from '@/features/settings/modal/settings-sidebar'; diff --git a/frontend/src/features/settings/modal/settings-sidebar.tsx b/client/src/features/settings/modal/settings-sidebar.tsx similarity index 99% rename from frontend/src/features/settings/modal/settings-sidebar.tsx rename to client/src/features/settings/modal/settings-sidebar.tsx index 1c18a7ad..04269512 100644 --- a/frontend/src/features/settings/modal/settings-sidebar.tsx +++ b/client/src/features/settings/modal/settings-sidebar.tsx @@ -1,5 +1,3 @@ -'use client'; - import React, { useState } from 'react'; import classes from '@/features/settings/modal/modal.module.css'; import { IconBell, IconFingerprint, IconReceipt, IconSettingsCog, IconUser, IconUsers } from '@tabler/icons-react'; diff --git a/frontend/src/features/settings/workspace/members/components/workspace-invite-form.tsx b/client/src/features/settings/workspace/members/components/workspace-invite-form.tsx similarity index 98% rename from frontend/src/features/settings/workspace/members/components/workspace-invite-form.tsx rename to client/src/features/settings/workspace/members/components/workspace-invite-form.tsx index add22bcf..00809167 100644 --- a/frontend/src/features/settings/workspace/members/components/workspace-invite-form.tsx +++ b/client/src/features/settings/workspace/members/components/workspace-invite-form.tsx @@ -1,5 +1,3 @@ -'use client'; - import { Group, Box, diff --git a/frontend/src/features/settings/workspace/members/components/workspace-invite-modal.tsx b/client/src/features/settings/workspace/members/components/workspace-invite-modal.tsx similarity index 98% rename from frontend/src/features/settings/workspace/members/components/workspace-invite-modal.tsx rename to client/src/features/settings/workspace/members/components/workspace-invite-modal.tsx index 9deed565..623be3af 100644 --- a/frontend/src/features/settings/workspace/members/components/workspace-invite-modal.tsx +++ b/client/src/features/settings/workspace/members/components/workspace-invite-modal.tsx @@ -1,5 +1,3 @@ -'use client'; - import { IconUserPlus } from '@tabler/icons-react'; import { WorkspaceInviteForm } from '@/features/settings/workspace/members/components/workspace-invite-form'; import { Button, Divider, Modal, ScrollArea, Text } from '@mantine/core'; diff --git a/frontend/src/features/settings/workspace/members/components/workspace-invite-section.tsx b/client/src/features/settings/workspace/members/components/workspace-invite-section.tsx similarity index 98% rename from frontend/src/features/settings/workspace/members/components/workspace-invite-section.tsx rename to client/src/features/settings/workspace/members/components/workspace-invite-section.tsx index bae66d35..d357631b 100644 --- a/frontend/src/features/settings/workspace/members/components/workspace-invite-section.tsx +++ b/client/src/features/settings/workspace/members/components/workspace-invite-section.tsx @@ -1,5 +1,3 @@ -'use client'; - import { useAtom } from 'jotai'; import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; import React, { useEffect, useState } from 'react'; diff --git a/frontend/src/features/settings/workspace/members/components/workspace-members-table.tsx b/client/src/features/settings/workspace/members/components/workspace-members-table.tsx similarity index 99% rename from frontend/src/features/settings/workspace/members/components/workspace-members-table.tsx rename to client/src/features/settings/workspace/members/components/workspace-members-table.tsx index 80280f7c..3c38d8e4 100644 --- a/frontend/src/features/settings/workspace/members/components/workspace-members-table.tsx +++ b/client/src/features/settings/workspace/members/components/workspace-members-table.tsx @@ -1,5 +1,3 @@ -'use client'; - import { useAtom } from 'jotai'; import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; import { useQuery } from '@tanstack/react-query'; diff --git a/frontend/src/features/settings/workspace/members/workspace-members.tsx b/client/src/features/settings/workspace/members/workspace-members.tsx similarity index 98% rename from frontend/src/features/settings/workspace/members/workspace-members.tsx rename to client/src/features/settings/workspace/members/workspace-members.tsx index 36140e80..5be83fab 100644 --- a/frontend/src/features/settings/workspace/members/workspace-members.tsx +++ b/client/src/features/settings/workspace/members/workspace-members.tsx @@ -1,5 +1,3 @@ -'use client'; - import WorkspaceInviteSection from '@/features/settings/workspace/members/components/workspace-invite-section'; import React from 'react'; import WorkspaceInviteModal from '@/features/settings/workspace/members/components/workspace-invite-modal'; diff --git a/frontend/src/features/settings/workspace/settings/components/workspace-name-form.tsx b/client/src/features/settings/workspace/settings/components/workspace-name-form.tsx similarity index 99% rename from frontend/src/features/settings/workspace/settings/components/workspace-name-form.tsx rename to client/src/features/settings/workspace/settings/components/workspace-name-form.tsx index 2ba87971..73e8b9d7 100644 --- a/frontend/src/features/settings/workspace/settings/components/workspace-name-form.tsx +++ b/client/src/features/settings/workspace/settings/components/workspace-name-form.tsx @@ -1,5 +1,3 @@ -'use client'; - import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; import { useAtom } from 'jotai'; import * as z from 'zod'; diff --git a/frontend/src/features/settings/workspace/settings/workspace-settings.tsx b/client/src/features/settings/workspace/settings/workspace-settings.tsx similarity index 92% rename from frontend/src/features/settings/workspace/settings/workspace-settings.tsx rename to client/src/features/settings/workspace/settings/workspace-settings.tsx index 357787bb..1c80cb18 100644 --- a/frontend/src/features/settings/workspace/settings/workspace-settings.tsx +++ b/client/src/features/settings/workspace/settings/workspace-settings.tsx @@ -1,5 +1,3 @@ -'use client'; - import WorkspaceNameForm from '@/features/settings/workspace/settings/components/workspace-name-form'; export default function WorkspaceSettings() { diff --git a/frontend/src/features/user/atoms/current-user-atom.ts b/client/src/features/user/atoms/current-user-atom.ts similarity index 100% rename from frontend/src/features/user/atoms/current-user-atom.ts rename to client/src/features/user/atoms/current-user-atom.ts diff --git a/frontend/src/features/user/hooks/use-current-user.ts b/client/src/features/user/hooks/use-current-user.ts similarity index 100% rename from frontend/src/features/user/hooks/use-current-user.ts rename to client/src/features/user/hooks/use-current-user.ts diff --git a/frontend/src/features/user/services/user-service.ts b/client/src/features/user/services/user-service.ts similarity index 100% rename from frontend/src/features/user/services/user-service.ts rename to client/src/features/user/services/user-service.ts diff --git a/frontend/src/features/user/types/user.types.ts b/client/src/features/user/types/user.types.ts similarity index 100% rename from frontend/src/features/user/types/user.types.ts rename to client/src/features/user/types/user.types.ts diff --git a/frontend/src/features/user/user-provider.tsx b/client/src/features/user/user-provider.tsx similarity index 97% rename from frontend/src/features/user/user-provider.tsx rename to client/src/features/user/user-provider.tsx index 610305dd..ccdcc8e7 100644 --- a/frontend/src/features/user/user-provider.tsx +++ b/client/src/features/user/user-provider.tsx @@ -1,5 +1,3 @@ -'use client'; - import { useAtom } from 'jotai'; import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; import React, { useEffect } from 'react'; diff --git a/frontend/src/features/workspace/services/workspace-service.ts b/client/src/features/workspace/services/workspace-service.ts similarity index 100% rename from frontend/src/features/workspace/services/workspace-service.ts rename to client/src/features/workspace/services/workspace-service.ts diff --git a/frontend/src/features/workspace/types/workspace.types.ts b/client/src/features/workspace/types/workspace.types.ts similarity index 100% rename from frontend/src/features/workspace/types/workspace.types.ts rename to client/src/features/workspace/types/workspace.types.ts diff --git a/frontend/src/lib/api-client.ts b/client/src/lib/api-client.ts similarity index 95% rename from frontend/src/lib/api-client.ts rename to client/src/lib/api-client.ts index e7e41026..f1863222 100644 --- a/frontend/src/lib/api-client.ts +++ b/client/src/lib/api-client.ts @@ -3,7 +3,7 @@ import Cookies from "js-cookie"; import Routes from "@/lib/routes"; const api: AxiosInstance = axios.create({ - baseURL: process.env.NEXT_PUBLIC_BACKEND_API_URL, + baseURL: import.meta.env.VITE_BACKEND_API_URL }); api.interceptors.request.use(config => { diff --git a/frontend/src/lib/jotai-helper.ts b/client/src/lib/jotai-helper.ts similarity index 100% rename from frontend/src/lib/jotai-helper.ts rename to client/src/lib/jotai-helper.ts diff --git a/frontend/src/lib/routes.ts b/client/src/lib/routes.ts similarity index 100% rename from frontend/src/lib/routes.ts rename to client/src/lib/routes.ts diff --git a/client/src/main.tsx b/client/src/main.tsx new file mode 100644 index 00000000..b2f8cb8f --- /dev/null +++ b/client/src/main.tsx @@ -0,0 +1,29 @@ +import '@mantine/core/styles.css'; +import '@mantine/spotlight/styles.css'; +import '@mantine/tiptap/styles.css'; + +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.tsx'; +import { theme } from '@/theme'; +import { MantineProvider } from '@mantine/core'; +import { TanstackProvider } from '@/components/providers/tanstack-provider'; +import CustomToaster from '@/components/ui/custom-toaster'; +import { BrowserRouter } from 'react-router-dom'; + +const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); + +root.render( + + + + + + + + , +); + + + + diff --git a/frontend/src/app/(auth)/layout.tsx b/client/src/pages/auth/layout.tsx similarity index 100% rename from frontend/src/app/(auth)/layout.tsx rename to client/src/pages/auth/layout.tsx diff --git a/frontend/src/app/(auth)/login/page.tsx b/client/src/pages/auth/login.tsx similarity index 89% rename from frontend/src/app/(auth)/login/page.tsx rename to client/src/pages/auth/login.tsx index 287f9418..96c6c116 100644 --- a/frontend/src/app/(auth)/login/page.tsx +++ b/client/src/pages/auth/login.tsx @@ -1,5 +1,3 @@ -'use client'; - import { LoginForm } from '@/features/auth/components/login-form'; export default function LoginPage() { diff --git a/frontend/src/app/(auth)/signup/page.tsx b/client/src/pages/auth/signup.tsx similarity index 90% rename from frontend/src/app/(auth)/signup/page.tsx rename to client/src/pages/auth/signup.tsx index 884e90b7..1e078770 100644 --- a/frontend/src/app/(auth)/signup/page.tsx +++ b/client/src/pages/auth/signup.tsx @@ -1,5 +1,3 @@ -'use client'; - import { SignUpForm } from '@/features/auth/components/sign-up-form'; export default function SignUpPage() { diff --git a/frontend/src/app/(dashboard)/home/page.tsx b/client/src/pages/dashboard/home.tsx similarity index 80% rename from frontend/src/app/(dashboard)/home/page.tsx rename to client/src/pages/dashboard/home.tsx index 2befe83a..81356ba9 100644 --- a/frontend/src/app/(dashboard)/home/page.tsx +++ b/client/src/pages/dashboard/home.tsx @@ -1,8 +1,5 @@ -'use client'; - import { useAtom } from 'jotai'; import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; -import usePage from '@/features/page/hooks/usePage'; export default function Home() { const [currentUser] = useAtom(currentUserAtom); @@ -10,7 +7,6 @@ export default function Home() { return ( <> Hello {currentUser && currentUser.user.name}! - ); } diff --git a/client/src/pages/page/page.tsx b/client/src/pages/page/page.tsx new file mode 100644 index 00000000..9c8b87f7 --- /dev/null +++ b/client/src/pages/page/page.tsx @@ -0,0 +1,8 @@ +import { useParams } from 'react-router-dom'; +import Editor from '@/features/editor/editor'; + +export default function Page() { + const { pageId } = useParams(); + + return ; +} diff --git a/frontend/src/components/welcome/welcome.tsx b/client/src/pages/welcome.tsx similarity index 89% rename from frontend/src/components/welcome/welcome.tsx rename to client/src/pages/welcome.tsx index 60082ff6..21fd5de0 100644 --- a/frontend/src/components/welcome/welcome.tsx +++ b/client/src/pages/welcome.tsx @@ -1,5 +1,5 @@ import { Title, Text } from '@mantine/core'; -import { ThemeToggle } from '../theme-toggle'; +import { ThemeToggle } from '@/components/theme-toggle'; export function Welcome() { return ( diff --git a/frontend/src/app/theme.ts b/client/src/theme.ts similarity index 85% rename from frontend/src/app/theme.ts rename to client/src/theme.ts index 63df4d85..a3bea325 100644 --- a/frontend/src/app/theme.ts +++ b/client/src/theme.ts @@ -1,5 +1,3 @@ -'use client'; - import { createTheme } from '@mantine/core'; export const theme = createTheme({ diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/client/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 00000000..dc77fc47 --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": false, + "strictNullChecks": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/client/tsconfig.node.json b/client/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/client/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/client/vite.config.ts b/client/vite.config.ts new file mode 100644 index 00000000..4c714346 --- /dev/null +++ b/client/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': '/src' + } + } +}) diff --git a/frontend/.env.example b/frontend/.env.example deleted file mode 100644 index 57c5257d..00000000 --- a/frontend/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -NEXT_PUBLIC_BACKEND_API_URL=http://localhost:3001 -NEXT_PUBLIC_COLLABORATION_URL= diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json deleted file mode 100644 index bffb357a..00000000 --- a/frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index fa76bed9..00000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -.env -package-lock.json -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index aaba1636..00000000 --- a/frontend/README.md +++ /dev/null @@ -1,26 +0,0 @@ -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -``` - -Open [http://localhost:3001](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/workspace-members.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! diff --git a/frontend/next.config.js b/frontend/next.config.js deleted file mode 100644 index 767719fc..00000000 --- a/frontend/next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {} - -module.exports = nextConfig diff --git a/frontend/src/app/(dashboard)/(page)/p/[pageId]/page.tsx b/frontend/src/app/(dashboard)/(page)/p/[pageId]/page.tsx deleted file mode 100644 index 7fc7b9a3..00000000 --- a/frontend/src/app/(dashboard)/(page)/p/[pageId]/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; - -import { useParams } from 'next/navigation'; -import dynamic from 'next/dynamic'; - -const Editor = dynamic(() => import("@/features/editor/Editor"), { - ssr: false, -}); - -export default function Page() { - const { pageId } = useParams(); - - return ( - - ); -} diff --git a/frontend/src/app/(dashboard)/layout.tsx b/frontend/src/app/(dashboard)/layout.tsx deleted file mode 100644 index 941c2a9b..00000000 --- a/frontend/src/app/(dashboard)/layout.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; - -import dynamic from 'next/dynamic'; -import { UserProvider } from '@/features/user/user-provider'; - -const Shell = dynamic(() => import('./shell'), { - ssr: false, -}); - -export default function DashboardLayout({ children }: { - children: React.ReactNode -}) { - - return ( - - - {children} - - - ); -} diff --git a/frontend/src/app/favicon.ico b/frontend/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx deleted file mode 100644 index 4b9861ee..00000000 --- a/frontend/src/app/layout.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import '@mantine/core/styles.css'; -import '@mantine/spotlight/styles.css'; -import '@mantine/tiptap/styles.css'; - -import type { Metadata } from 'next'; -import { TanstackProvider } from '@/components/providers/tanstack-provider'; -import CustomToaster from '@/components/ui/custom-toaster'; -import { theme } from '@/app/theme'; -import { ColorSchemeScript, MantineProvider } from '@mantine/core'; - -export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', - viewport: { - width: 'device-width', - initialScale: 1, - maximumScale: 1, - }, -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - - - - - - - {children} - - - - - - ); -} diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx deleted file mode 100644 index be72b1a5..00000000 --- a/frontend/src/app/page.tsx +++ /dev/null @@ -1,6 +0,0 @@ -'use client' -import { Welcome } from '@/components/welcome/welcome'; - -export default function Home() { - return ; -} diff --git a/frontend/src/components/icons.tsx b/frontend/src/components/icons.tsx deleted file mode 100644 index b489acab..00000000 --- a/frontend/src/components/icons.tsx +++ /dev/null @@ -1,48 +0,0 @@ -type IconProps = React.HTMLAttributes - -export const Icons = { - - logo: (props: IconProps) => ( - - - - - - ), - spinner: (props: IconProps) => ( - - - - ), -} diff --git a/frontend/src/features/editor/Editor.tsx b/frontend/src/features/editor/Editor.tsx deleted file mode 100644 index d3b28be7..00000000 --- a/frontend/src/features/editor/Editor.tsx +++ /dev/null @@ -1,110 +0,0 @@ -'use client'; - -import { HocuspocusProvider } from '@hocuspocus/provider'; -import * as Y from 'yjs'; -import { EditorContent, useEditor } from '@tiptap/react'; -import { StarterKit } from '@tiptap/starter-kit'; -import { Placeholder } from '@tiptap/extension-placeholder'; -import { Collaboration } from '@tiptap/extension-collaboration'; -import { CollaborationCursor } from '@tiptap/extension-collaboration-cursor'; -import { useEffect, useLayoutEffect, useState } from 'react'; -import { useAtom } from 'jotai/index'; -import { currentUserAtom } from '@/features/user/atoms/current-user-atom'; -import { authTokensAtom } from '@/features/auth/atoms/auth-tokens-atom'; -import useCollaborationUrl from '@/features/editor/hooks/use-collaboration-url'; -import '@/features/editor/styles/editor.css'; - -interface EditorProps{ - pageId: string, -} - -const colors = ['#958DF1', '#F98181', '#FBBC88', '#FAF594', '#70CFF8', '#94FADB', '#B9F18D'] -const getRandomElement = list => list[Math.floor(Math.random() * list.length)] -const getRandomColor = () => getRandomElement(colors) - -export default function Editor({ pageId }: EditorProps ) { - const [token] = useAtom(authTokensAtom); - const collaborationURL = useCollaborationUrl(); - const [provider, setProvider] = useState(); - const [doc, setDoc] = useState() - - useLayoutEffect(() => { - if (token) { - const ydoc = new Y.Doc(); - - const provider = new HocuspocusProvider({ - url: collaborationURL, - name: pageId, - document: ydoc, - token: token?.accessToken, - }); - - setDoc(ydoc); - setProvider(provider); - - return () => { - ydoc.destroy(); - provider.destroy(); - }; - } - }, [pageId, token]); - console.log(token) - - if(!doc || !provider){ - return null; - } - - console.log(doc) - - return ( - - ); -} - -interface TiptapEditorProps { - ydoc: Y.Doc, - provider: HocuspocusProvider -} - -function TiptapEditor({ ydoc, provider }: TiptapEditorProps) { - const [currentUser] = useAtom(currentUserAtom); - - const extensions = [ - StarterKit.configure({ - history: false, - }), - Placeholder.configure({ - placeholder: 'Write here', - }), - Collaboration.configure({ - document: ydoc, - }), - CollaborationCursor.configure({ - provider - }), - ]; - - const editor = useEditor({ - extensions: extensions, - }); - - useEffect(() => { - if (editor && currentUser.user){ - editor.chain().focus().updateUser({...currentUser.user, color: getRandomColor()}).run() - } - }, [editor, currentUser.user]) - - useEffect(() => { - provider.on('status', event => { - console.log(event) - }) - - }, [provider]) - - - return ( - <> - - - ); -} diff --git a/frontend/src/features/editor/styles/editor.css b/frontend/src/features/editor/styles/editor.css deleted file mode 100644 index 759cff9a..00000000 --- a/frontend/src/features/editor/styles/editor.css +++ /dev/null @@ -1,26 +0,0 @@ -/* Give a remote user a caret */ -.collaboration-cursor__caret { - border-left: 1px solid #0d0d0d; - border-right: 1px solid #0d0d0d; - margin-left: -1px; - margin-right: -1px; - pointer-events: none; - position: relative; - word-break: normal; -} - -/* Render the username above the caret */ -.collaboration-cursor__label { - border-radius: 3px 3px 3px 0; - color: #0d0d0d; - font-size: 12px; - font-style: normal; - font-weight: 600; - left: -1px; - line-height: normal; - padding: 0.1rem 0.3rem; - position: absolute; - top: -1.4em; - user-select: none; - white-space: nowrap; -} diff --git a/frontend/src/features/page/tree/components/merge-refs.ts b/frontend/src/features/page/tree/components/merge-refs.ts deleted file mode 100644 index 1f974d23..00000000 --- a/frontend/src/features/page/tree/components/merge-refs.ts +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; - -type AnyRef = React.MutableRefObject | React.RefCallback | null; - -export default function mergeRefs(...refs: AnyRef[]) { - return (instance: any) => { - refs.forEach((ref) => { - if (typeof ref === "function") { - ref(instance); - } else if (ref != null) { - ref.current = instance; - } - }); - }; -} \ No newline at end of file diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index f15c41a8..00000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": false, - "strictNullChecks": false, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -}