diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 1022108..0000000 --- a/.editorconfig +++ /dev/null @@ -1,14 +0,0 @@ -# Editor configuration, see http://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true -max_line_length = 80 - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..d4b2cb8 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,37 @@ +/** @type {import("eslint").Linter.Config} */ +const config = { + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, + plugins: ["@typescript-eslint"], + extends: [ + "plugin:@next/next/recommended", + "plugin:@typescript-eslint/recommended-type-checked", + "plugin:@typescript-eslint/stylistic-type-checked", + ], + rules: { + // These opinionated rules are enabled in stylistic-type-checked above. + // Feel free to reconfigure them to your own preference. + "@typescript-eslint/array-type": "off", + "@typescript-eslint/consistent-type-definitions": "off", + + "@typescript-eslint/consistent-type-imports": [ + "warn", + { + prefer: "type-imports", + fixStyle: "inline-type-imports", + }, + ], + "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], + "@typescript-eslint/require-await": "off", + "@typescript-eslint/no-misused-promises": [ + "error", + { + checksVoidReturn: { attributes: false }, + }, + ], + }, +}; + +module.exports = config; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/.gitignore b/.gitignore index bd707d9..2971a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,14 @@ # testing /coverage +# database +/prisma/db.sqlite +/prisma/db.sqlite-journal + # next.js /.next/ /out/ +next-env.d.ts # production /build @@ -23,14 +28,15 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +.pnpm-debug.log* # local env files +# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables .env +.env*.local # vercel .vercel # typescript *.tsbuildinfo -next-env.d.ts -.krud/ diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 39e33eb..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index 230c6e0..0000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - postgresql - true - org.postgresql.Driver - jdbc:postgresql://localhost:5432/parentgrine - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index a862b72..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/parentgrine-server.iml b/.idea/parentgrine-server.iml deleted file mode 100644 index bc52044..0000000 --- a/.idea/parentgrine-server.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml deleted file mode 100644 index 6df4889..0000000 --- a/.idea/sqldialects.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 943f43d..0000000 --- a/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "trailingComma": "es5", - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "singleAttributePerLine": true -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 2727a18..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Next.js: debug server-side", - "type": "node-terminal", - "request": "launch", - "command": "bun dev" - }, - { - "name": "Next.js: debug client-side", - "type": "chrome", - "request": "launch", - "url": "http://localhost:3000" - }, - { - "name": "Next.js: debug full stack", - "type": "node-terminal", - "request": "launch", - "command": "bun dev", - "serverReadyAction": { - "pattern": "- Local:.+(https?://.+)", - "uriFormat": "%s", - "action": "debugWithChrome" - } - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index f2a0327..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "editor.fontFamily": "'Hack Nerd Font Mono', 'monospace', monospace", - "files.exclude": { - "node_modules": true, - ".idea": true, - ".vscode": true, - ".next": true, - "**/.git": true, - "**/.svn": true, - "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/Thumbs.db": true - }, - "workbench.colorTheme": "Monokai Classic", - "workbench.iconTheme": "vscode-icontheme-nomo-dark-macos", - "workbench.colorCustomizations": { - "activityBar.activeBackground": "#ab307e", - "activityBar.background": "#ab307e", - "activityBar.foreground": "#e7e7e7", - "activityBar.inactiveForeground": "#e7e7e799", - "activityBarBadge.background": "#25320e", - "activityBarBadge.foreground": "#e7e7e7", - "commandCenter.border": "#e7e7e799", - "sash.hoverBorder": "#ab307e", - "statusBar.background": "#832561", - "statusBar.foreground": "#e7e7e7", - "statusBarItem.hoverBackground": "#ab307e", - "statusBarItem.remoteBackground": "#832561", - "statusBarItem.remoteForeground": "#e7e7e7", - "titleBar.activeBackground": "#832561", - "titleBar.activeForeground": "#e7e7e7", - "titleBar.inactiveBackground": "#83256199", - "titleBar.inactiveForeground": "#e7e7e799" - }, - "peacock.color": "#832561", - "sqltools.connections": [ - { - "previewLimit": 50, - "server": "localhost", - "port": 5432, - "driver": "PostgreSQL", - "name": "localhost", - "username": "postgres", - "password": "hackme", - "database": "parentgrine" - } - ] -} diff --git a/README.md b/README.md index c403366..fba19ed 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,28 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +# Create T3 App -## Getting Started +This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`. -First, run the development server: +## What's next? How do I make an app with this? -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` +We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary. -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help. -You can start editing the page by modifying `app/page.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. +- [Next.js](https://nextjs.org) +- [NextAuth.js](https://next-auth.js.org) +- [Prisma](https://prisma.io) +- [Tailwind CSS](https://tailwindcss.com) +- [tRPC](https://trpc.io) ## Learn More -To learn more about Next.js, take a look at the following resources: +To learn more about the [T3 Stack](https://create.t3.gg/), 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. +- [Documentation](https://create.t3.gg/) +- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome! -## Deploy on Vercel +## How do I deploy this? -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information. diff --git a/bun.lockb b/bun.lockb index e35a745..c7a3cbe 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components.json b/components.json deleted file mode 100644 index b050396..0000000 --- a/components.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "default", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "tailwind.config.ts", - "css": "app/globals.css", - "baseColor": "zinc", - "cssVariables": true - }, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils" - } -} diff --git a/drizzle.config.ts b/drizzle.config.ts index b4bf7c1..8da6dea 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,14 +1,11 @@ -import type { Config } from 'drizzle-kit' -import { env } from '@/env.mjs' +import { type Config } from "drizzle-kit"; + +import { env } from "@/env"; -if (!env.DATABASE_URL) { - throw new Error('DATABASE_URL is missing') -} export default { - schema: './src/db', - out: './drizzle', - driver: 'pg', + schema: "./src/server/db/schema.ts", + driver: "pg", dbCredentials: { - connectionString: env.DATABASE_URL as string, + connectionString: env.DATABASE_URL, }, -} satisfies Config +} satisfies Config; diff --git a/drizzle/0000_watery_zaladane.sql b/drizzle/0000_watery_zaladane.sql deleted file mode 100644 index c2670ed..0000000 --- a/drizzle/0000_watery_zaladane.sql +++ /dev/null @@ -1,77 +0,0 @@ -CREATE TABLE IF NOT EXISTS "account" ( - "userId" uuid NOT NULL, - "type" text NOT NULL, - "provider" text NOT NULL, - "providerAccountId" text NOT NULL, - "refresh_token" text, - "access_token" text, - "expires_at" integer, - "token_type" text, - "scope" text, - "id_token" text, - "session_state" text, - CONSTRAINT "account_provider_providerAccountId_pk" PRIMARY KEY("provider","providerAccountId") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "child" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "name" varchar(256), - "email" varchar(256), - "phone" varchar(256), - "key" varchar(256), - "parent_id" uuid NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "device" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "device_id" varchar NOT NULL, - "child_id" uuid NOT NULL, - "api_key" varchar NOT NULL, - "pin" integer NOT NULL, - "expires" timestamp DEFAULT now - () - + interval '1 hour', - CONSTRAINT "device_device_id_unique" UNIQUE("device_id"), - CONSTRAINT "device_api_key_unique" UNIQUE("api_key") -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "ping" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "device_id" uuid NOT NULL, - "latitude" double precision NOT NULL, - "longitude" double precision NOT NULL, - "timestamp" timestamp NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "session" ( - "sessionToken" text PRIMARY KEY NOT NULL, - "userId" uuid NOT NULL, - "expires" timestamp NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "user" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "name" text, - "email" text NOT NULL, - "emailVerified" timestamp, - "image" text -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "verification_token" ( - "identifier" text NOT NULL, - "token" text NOT NULL, - "expires" timestamp NOT NULL, - CONSTRAINT "verification_token_identifier_token_pk" PRIMARY KEY("identifier","token") -); ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "account" ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "session" ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json deleted file mode 100644 index 96196e9..0000000 --- a/drizzle/meta/0000_snapshot.json +++ /dev/null @@ -1,383 +0,0 @@ -{ - "id": "7ac914a6-b952-4605-8341-0b7f522e85a5", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "5", - "dialect": "pg", - "tables": { - "account": { - "name": "account", - "schema": "", - "columns": { - "userId": { - "name": "userId", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "providerAccountId": { - "name": "providerAccountId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "token_type": { - "name": "token_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "session_state": { - "name": "session_state", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "account_userId_user_id_fk": { - "name": "account_userId_user_id_fk", - "tableFrom": "account", - "tableTo": "user", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "account_provider_providerAccountId_pk": { - "name": "account_provider_providerAccountId_pk", - "columns": [ - "provider", - "providerAccountId" - ] - } - }, - "uniqueConstraints": {} - }, - "child": { - "name": "child", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "phone": { - "name": "phone", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "key": { - "name": "key", - "type": "varchar(256)", - "primaryKey": false, - "notNull": false - }, - "parent_id": { - "name": "parent_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "device": { - "name": "device", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "device_id": { - "name": "device_id", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "child_id": { - "name": "child_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "api_key": { - "name": "api_key", - "type": "varchar", - "primaryKey": false, - "notNull": true - }, - "pin": { - "name": "pin", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "timestamp", - "primaryKey": false, - "notNull": false, - "default": "now\n ()\n + interval '1 hour'" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "device_device_id_unique": { - "name": "device_device_id_unique", - "nullsNotDistinct": false, - "columns": [ - "device_id" - ] - }, - "device_api_key_unique": { - "name": "device_api_key_unique", - "nullsNotDistinct": false, - "columns": [ - "api_key" - ] - } - } - }, - "ping": { - "name": "ping", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "device_id": { - "name": "device_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "latitude": { - "name": "latitude", - "type": "double precision", - "primaryKey": false, - "notNull": true - }, - "longitude": { - "name": "longitude", - "type": "double precision", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "session": { - "name": "session", - "schema": "", - "columns": { - "sessionToken": { - "name": "sessionToken", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "userId": { - "name": "userId", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "timestamp", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "session_userId_user_id_fk": { - "name": "session_userId_user_id_fk", - "tableFrom": "session", - "tableTo": "user", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "user": { - "name": "user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "emailVerified": { - "name": "emailVerified", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "verification_token": { - "name": "verification_token", - "schema": "", - "columns": { - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "timestamp", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": { - "verification_token_identifier_token_pk": { - "name": "verification_token_identifier_token_pk", - "columns": [ - "identifier", - "token" - ] - } - }, - "uniqueConstraints": {} - } - }, - "enums": {}, - "schemas": {}, - "_meta": { - "schemas": {}, - "tables": {}, - "columns": {} - } -} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json deleted file mode 100644 index 9f2ac7a..0000000 --- a/drizzle/meta/_journal.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "5", - "dialect": "pg", - "entries": [ - { - "idx": 0, - "version": "5", - "when": 1703185817079, - "tag": "0000_watery_zaladane", - "breakpoints": true - } - ] -} \ No newline at end of file diff --git a/next.config.js b/next.config.js index bc29a32..9bfe4a0 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,10 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - env: {}, -} +/** + * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful + * for Docker builds. + */ +await import("./src/env.js"); -module.exports = nextConfig +/** @type {import("next").NextConfig} */ +const config = {}; + +export default config; diff --git a/package.json b/package.json index 057ef9b..ee46b75 100644 --- a/package.json +++ b/package.json @@ -1,93 +1,55 @@ { - "name": "parentgrine", + "name": "parentgrine-server", "version": "0.1.0", "private": true, + "type": "module", "scripts": { - "dev2": "next dev", - "dev": "NODE_ENV=development next dev -p 3002 & local-ssl-proxy --key /etc/letsencrypt/live/dev.fergl.ie/privkey.pem --cert /etc/letsencrypt/live/dev.fergl.ie/fullchain.pem --source 3000 --target 3002", - "drizzle:migrate": "node --loader esbuild-register/loader -r esbuild-register ./src/db/migrate.ts", - "drizzle:seed": "node --loader esbuild-register/loader -r esbuild-register ./src/db/seed.ts", "build": "next build", - "start": "next start", - "lint": "next lint" + "db:push": "dotenv drizzle-kit push:mysql", + "db:studio": "dotenv drizzle-kit studio", + "dev": "NODE_ENV=development next dev -p 3002 & local-ssl-proxy --key /etc/letsencrypt/live/dev.fergl.ie/privkey.pem --cert /etc/letsencrypt/live/dev.fergl.ie/fullchain.pem --source 3000 --target 3002", + "lint": "next lint", + "start": "next start" }, "dependencies": { - "@auth/drizzle-adapter": "^0.3.12", - "@hookform/resolvers": "^3.3.2", - "@microsoft/signalr": "^8.0.0", - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-alert-dialog": "^1.0.5", - "@radix-ui/react-aspect-ratio": "^1.0.3", - "@radix-ui/react-avatar": "^1.0.4", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-collapsible": "^1.0.3", - "@radix-ui/react-context-menu": "^2.1.5", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-dropdown-menu": "^2.0.6", - "@radix-ui/react-hover-card": "^1.0.7", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-menubar": "^1.0.4", - "@radix-ui/react-navigation-menu": "^1.1.4", - "@radix-ui/react-popover": "^1.0.7", - "@radix-ui/react-progress": "^1.0.3", - "@radix-ui/react-radio-group": "^1.1.3", - "@radix-ui/react-scroll-area": "^1.0.5", - "@radix-ui/react-select": "^2.0.0", - "@radix-ui/react-separator": "^1.0.3", - "@radix-ui/react-slider": "^1.1.2", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.0.3", - "@radix-ui/react-tabs": "^1.0.4", - "@radix-ui/react-toast": "^1.1.5", - "@radix-ui/react-toggle": "^1.0.3", - "@radix-ui/react-tooltip": "^1.0.7", - "@t3-oss/env-core": "^0.7.1", + "@auth/drizzle-adapter": "^0.3.6", + "@planetscale/database": "^1.11.0", "@t3-oss/env-nextjs": "^0.7.1", - "@tanstack/react-query": "^5.14.2", - "@tanstack/react-query-devtools": "^5.14.5", - "axios": "^1.6.2", - "class-variance-authority": "^0.7.0", - "clsx": "^2.0.0", - "cmdk": "^0.2.0", - "date-fns": "^3.0.5", - "dotenv": "^16.3.1", - "drizzle-orm": "^0.29.1", - "esbuild-register": "^3.5.0", - "generate-api-key": "^1.0.2", - "http-status-codes": "^2.3.0", - "leaflet": "^1.9.4", - "local-ssl-proxy": "^2.0.5", - "lucide-react": "^0.299.0", - "next": "14.0.4", + "@tanstack/react-query": "^4.36.1", + "@trpc/client": "^10.43.6", + "@trpc/next": "^10.43.6", + "@trpc/react-query": "^10.43.6", + "@trpc/server": "^10.43.6", + "drizzle-orm": "^0.28.5", + "next": "^14.0.3", "next-auth": "^4.24.5", - "next-themes": "^0.2.1", "pg": "^8.11.3", "postgres": "^3.4.3", - "react": "^18", - "react-day-picker": "^8.9.1", - "react-dom": "^18", - "react-hook-form": "^7.49.2", - "react-leaflet": "^4.2.1", - "react-qr-code": "^2.0.12", - "socket.io": "^4.7.2", - "socket.io-client": "^4.7.2", - "swr": "^2.2.4", - "tailwind-merge": "^2.1.0", - "tailwindcss-animate": "^1.0.7", + "react": "18.2.0", + "react-dom": "18.2.0", + "server-only": "^0.0.1", + "superjson": "^2.2.1", "zod": "^3.22.4" }, "devDependencies": { - "@types/leaflet": "^1.9.8", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "autoprefixer": "^10", + "@next/eslint-plugin-next": "^14.0.3", + "@types/eslint": "^8.44.7", + "@types/node": "^18.17.0", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", + "@typescript-eslint/eslint-plugin": "^6.11.0", + "@typescript-eslint/parser": "^6.11.0", + "autoprefixer": "^10.4.14", + "dotenv-cli": "^7.3.0", "drizzle-kit": "^0.20.7", - "eslint": "^8", - "eslint-config-next": "14.0.4", - "postcss": "^8", - "prettier": "3.1.1", - "tailwindcss": "^3", - "typescript": "^5" + "eslint": "^8.54.0", + "postcss": "^8.4.31", + "prettier": "^3.1.0", + "prettier-plugin-tailwindcss": "^0.5.7", + "tailwindcss": "^3.3.5", + "typescript": "^5.1.6" + }, + "ct3aMetadata": { + "initVersion": "7.25.0" } } diff --git a/postcss.config.js b/postcss.config.cjs similarity index 57% rename from postcss.config.js rename to postcss.config.cjs index 33ad091..e305dd9 100644 --- a/postcss.config.js +++ b/postcss.config.cjs @@ -1,6 +1,8 @@ -module.exports = { +const config = { plugins: { tailwindcss: {}, autoprefixer: {}, }, -} +}; + +module.exports = config; diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..b2d59b4 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,6 @@ +/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ +const config = { + plugins: ["prettier-plugin-tailwindcss"], +}; + +export default config; diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png deleted file mode 100644 index cbd81c1..0000000 Binary files a/public/android-chrome-192x192.png and /dev/null differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png deleted file mode 100644 index 8d144a0..0000000 Binary files a/public/android-chrome-512x512.png and /dev/null differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index a033189..0000000 Binary files a/public/apple-touch-icon.png and /dev/null differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index c31bb38..0000000 Binary files a/public/favicon-16x16.png and /dev/null differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index dc9110b..0000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico index efb824e..b5336a4 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/site.webmanifest b/public/site.webmanifest deleted file mode 100644 index 4704116..0000000 --- a/public/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Parent Grin", - "short_name": "parentgrine", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} diff --git a/scripts/reset.sh b/scripts/reset.sh index eec76c7..b828a1f 100755 --- a/scripts/reset.sh +++ b/scripts/reset.sh @@ -15,4 +15,4 @@ bunx drizzle-kit generate:pg --config=./drizzle.config.ts bunx drizzle-kit push:pg --config=./drizzle.config.ts # bun run src/db/migrate.ts -bun run ./src/db/scripts/seed.ts +bun run ./src/server/db/scripts/seed.ts diff --git a/src/app/(auth)/signin/page.tsx b/src/app/(auth)/signin/page.tsx deleted file mode 100644 index 3d593a6..0000000 --- a/src/app/(auth)/signin/page.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { UserAuthForm } from '@/components/forms/user-auth-form'; -import { Icons } from '@/components/icons'; -import { buttonVariants } from '@/components/ui/button'; -import { cn } from '@/lib/utils'; -import Link from 'next/link'; -import React from 'react'; - -const SigninPage = () => { - return ( -
- - <> - - Back - - -
-
- -

- Welcome back or Hello? -

-

- Enter your email to sign in to your account -

-
- -
-
- ); -}; - -export default SigninPage; diff --git a/src/app/(parent)/children/page.tsx b/src/app/(parent)/children/page.tsx deleted file mode 100644 index 5c2d41a..0000000 --- a/src/app/(parent)/children/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import axios from 'axios'; -import ChildrenList from '@/components/children/children-list'; - -const ChildrenPage = async () => { - return ; -}; - -export default ChildrenPage; diff --git a/src/app/(parent)/dashboard/page.tsx b/src/app/(parent)/dashboard/page.tsx deleted file mode 100644 index a0ca486..0000000 --- a/src/app/(parent)/dashboard/page.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client'; -import React, { useEffect, useMemo, useState } from 'react'; -import ChildrenFilter from '@/components/children/children-filter'; -import dynamic from 'next/dynamic'; -import io from 'socket.io-client'; - -const DashboardPage = () => { - - //this needs to be a dynamic import - //otherwise it causes window not found errors - const Map = dynamic(() => import('@/components/maps/main-map'), { ssr: false }); - return ( -
-
- -
-
- -
-
- ); -}; - -export default DashboardPage; diff --git a/src/app/(parent)/debug/page.tsx b/src/app/(parent)/debug/page.tsx deleted file mode 100644 index 8ac293a..0000000 --- a/src/app/(parent)/debug/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import QRCode from 'react-qr-code'; - -const DebugPage = () => { - return ( -
- -
- ); -}; -export default DebugPage; diff --git a/src/app/(parent)/layout.tsx b/src/app/(parent)/layout.tsx deleted file mode 100644 index 6344c39..0000000 --- a/src/app/(parent)/layout.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { SiteHeader } from '@/components/header/site-header'; -import React from 'react'; -import { SocketProvider } from '@/lib/services/realtime/socket-provider'; - -type DashboardLayoutProps = { - children?: React.ReactNode -} -const DashboardLayout = async ({ children }: DashboardLayoutProps) => { - return ( - -
- -
{children}
-
-
- ); - -}; -export default DashboardLayout; diff --git a/src/app/_components/create-post.tsx b/src/app/_components/create-post.tsx new file mode 100644 index 0000000..fed989c --- /dev/null +++ b/src/app/_components/create-post.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { useState } from "react"; + +import { api } from "@/trpc/react"; + +export function CreatePost() { + const router = useRouter(); + const [name, setName] = useState(""); + + const createPost = api.post.create.useMutation({ + onSuccess: () => { + router.refresh(); + setName(""); + }, + }); + + return ( +
{ + e.preventDefault(); + createPost.mutate({ name }); + }} + className="flex flex-col gap-2" + > + setName(e.target.value)} + className="w-full rounded-full px-4 py-2 text-black" + /> + +
+ ); +} diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index ef714f0..1570f88 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,5 +1,7 @@ -import NextAuth from 'next-auth' -import authOptions from '@/lib/services/auth/config' +import NextAuth from "next-auth"; -const handler = NextAuth(authOptions) -export { handler as GET, handler as POST } +import { authOptions } from "@/server/auth"; + +// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment +const handler = NextAuth(authOptions); +export { handler as GET, handler as POST }; diff --git a/src/app/api/child/create/route.ts b/src/app/api/child/create/route.ts deleted file mode 100644 index 36ca131..0000000 --- a/src/app/api/child/create/route.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { newChildSchema } from '@/lib/validations/child'; -import { getServerAuthSession } from '@/lib/services/auth/config'; -import { createApiKey } from '@/lib/services/auth/api'; - -import { NextResponse } from 'next/server'; -import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import db from '@/db'; - -import { child } from '@/db/schema'; -import { users } from '@/db/schema'; -import { eq } from 'drizzle-orm'; -import { device } from '@/db/schema'; - -export async function POST(req: Request) { - const session = await getServerAuthSession(); - if (!session || !session.user?.email) - return NextResponse.next({ - statusText: getReasonPhrase(StatusCodes.UNAUTHORIZED), - status: StatusCodes.UNAUTHORIZED, - }); - - const body = await req.json(); - const user = await db - .selectDistinct({ id: users.id }) - .from(users) - .where(eq(users.email, session.user.email)); - - if (!user) { - return NextResponse.next({ - statusText: `Unable to find user id for ${session.user.email}`, - status: StatusCodes.INTERNAL_SERVER_ERROR, - }); - } - const { name } = newChildSchema.parse(body); - - const newChild = await db - .insert(child) - .values({ - parentId: user[0].id.toString(), - name, - }) - .returning(); - if (!newChild) { - return NextResponse.next({ - statusText: 'Error inserting child', - status: StatusCodes.INTERNAL_SERVER_ERROR, - }); - } - - return NextResponse.json({ status: 'success' }); -} diff --git a/src/app/api/child/register/route.ts b/src/app/api/child/register/route.ts deleted file mode 100644 index 2138181..0000000 --- a/src/app/api/child/register/route.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getServerAuthSession } from '@/lib/services/auth/config'; -import { NextResponse } from 'next/server'; -import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -export async function POST(req: Request) { - const body = await req.json(); -} diff --git a/src/app/api/child/route.ts b/src/app/api/child/route.ts deleted file mode 100644 index 5dfcefb..0000000 --- a/src/app/api/child/route.ts +++ /dev/null @@ -1,25 +0,0 @@ -import db from '@/db'; -import { child } from '@/db/schema'; -import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { NextResponse } from 'next/server'; -import { getServerAuthSession } from '@/lib/services/auth/config'; -import { eq } from 'drizzle-orm'; - -export async function GET(request: Request) { - const session = await getServerAuthSession(); - if (!session || !session.user) - return NextResponse.json( - { error: getReasonPhrase(StatusCodes.UNAUTHORIZED) }, - { status: StatusCodes.UNAUTHORIZED } - ); - const activeChildren = await db.query.child.findMany({ - where: eq(child.parentId, session.user.id), - with: { - devices: { - with: { pings: true }, - }, - }, - }); - - return NextResponse.json(activeChildren); -} diff --git a/src/app/api/device/connect/route.ts b/src/app/api/device/connect/route.ts deleted file mode 100644 index 1ac78e9..0000000 --- a/src/app/api/device/connect/route.ts +++ /dev/null @@ -1,58 +0,0 @@ -import db from '@/db'; -import { eq } from 'drizzle-orm'; -import { StatusCodes } from 'http-status-codes'; -import { child, device } from '@/db/schema'; -import { createApiKey } from '@/lib/services/auth/api'; -import { badRequest } from '@/app/api/responses'; - -const POST = async (req: Request, res: Response) => { - if (req.method === 'POST') { - const url = new URL(req.url); - const { deviceId, childId } = await req.json(); - console.log('route', 'childId', childId); - console.log('route', 'deviceId', deviceId); - - if (!childId || !deviceId) { - return badRequest('Invalid registration request'); - } - - const childToRegister = ( - await db.selectDistinct().from(child).where(eq(child.id, childId)) - )[0]; - - if (!childToRegister) { - return badRequest('Invalid registration request'); - } - - let done = false; - let pin = 2021; - while (!done) { - pin = Math.floor(1000 + Math.random() * 9000); - console.log('route', 'device/connect', 'checking for PIN', pin); - const exists = await db - .selectDistinct() - .from(device) - .where(eq(device.pin, pin)); - console.log('route', 'exists', exists); - done = exists.length === 0; - } - - const apiKey = createApiKey(); - await db - .insert(device) - .values({ - childId: childToRegister.id, - deviceId: deviceId, - pin, - apiKey: apiKey, - }) - .execute(); - return Response.json( - { childId, deviceId, pin, apiKey }, - { status: StatusCodes.CREATED } - ); - } - return badRequest('Invalid registration request'); -}; - -export { POST }; diff --git a/src/app/api/responses/index.ts b/src/app/api/responses/index.ts deleted file mode 100644 index 5cd6bad..0000000 --- a/src/app/api/responses/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { StatusCodes } from 'http-status-codes'; - -export const notAuthorised = () => - new Response('Not authorised', { - status: StatusCodes.BAD_REQUEST, - }); -export const badRequest = (message: string) => - new Response(message, { - status: StatusCodes.BAD_REQUEST, - }); diff --git a/src/app/api/trpc/[trpc]/route.ts b/src/app/api/trpc/[trpc]/route.ts new file mode 100644 index 0000000..c397112 --- /dev/null +++ b/src/app/api/trpc/[trpc]/route.ts @@ -0,0 +1,34 @@ +import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; +import { type NextRequest } from "next/server"; + +import { env } from "@/env"; +import { appRouter } from "@/server/api/root"; +import { createTRPCContext } from "@/server/api/trpc"; + +/** + * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when + * handling a HTTP request (e.g. when you make requests from Client Components). + */ +const createContext = async (req: NextRequest) => { + return createTRPCContext({ + headers: req.headers, + }); +}; + +const handler = (req: NextRequest) => + fetchRequestHandler({ + endpoint: "/api/trpc", + req, + router: appRouter, + createContext: () => createContext(req), + onError: + env.NODE_ENV === "development" + ? ({ path, error }) => { + console.error( + `❌ tRPC failed on ${path ?? ""}: ${error.message}` + ); + } + : undefined, + }); + +export { handler as GET, handler as POST }; diff --git a/src/app/globals.css b/src/app/globals.css deleted file mode 100644 index e765625..0000000 --- a/src/app/globals.css +++ /dev/null @@ -1,65 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 20 14.3% 4.1%; - --card: 0 0% 100%; - --card-foreground: 20 14.3% 4.1%; - --popover: 0 0% 100%; - --popover-foreground: 20 14.3% 4.1%; - --primary: 24.6 95% 53.1%; - --primary-foreground: 60 9.1% 97.8%; - --secondary: 60 4.8% 95.9%; - --secondary-foreground: 24 9.8% 10%; - --muted: 60 4.8% 95.9%; - --muted-foreground: 25 5.3% 44.7%; - --accent: 60 4.8% 95.9%; - --accent-foreground: 24 9.8% 10%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 60 9.1% 97.8%; - --border: 20 5.9% 90%; - --input: 20 5.9% 90%; - --ring: 24.6 95% 53.1%; - --radius: 0.75rem; - } - - .dark { - --background: 20 14.3% 4.1%; - --foreground: 60 9.1% 97.8%; - --card: 20 14.3% 4.1%; - --card-foreground: 60 9.1% 97.8%; - --popover: 20 14.3% 4.1%; - --popover-foreground: 60 9.1% 97.8%; - --primary: 20.5 90.2% 48.2%; - --primary-foreground: 60 9.1% 97.8%; - --secondary: 12 6.5% 15.1%; - --secondary-foreground: 60 9.1% 97.8%; - --muted: 12 6.5% 15.1%; - --muted-foreground: 24 5.4% 63.9%; - --accent: 12 6.5% 15.1%; - --accent-foreground: 60 9.1% 97.8%; - --destructive: 0 72.2% 50.6%; - --destructive-foreground: 60 9.1% 97.8%; - --border: 12 6.5% 15.1%; - --input: 12 6.5% 15.1%; - --ring: 20.5 90.2% 48.2%; - } -} - -.map { - width: 100%; - height: 40rem; -} -.leaflet-control { - z-index: 0 !important; -} -.leaflet-pane { - z-index: 0 !important; -} -.leaflet-top, -.leaflet-bottom { - z-index: 0 !important; -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index aa369d3..f3f249e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,26 +1,19 @@ -import React from 'react'; +import "@/styles/globals.css"; -import './globals.css'; -import 'leaflet/dist/leaflet.css'; +import { Inter } from "next/font/google"; +import { cookies } from "next/headers"; -import type { Metadata } from 'next'; -import { Sanchez } from 'next/font/google'; -import NextAuthProvider from '@/lib/services/auth/provider'; -import { ThemeProvider } from '@/components/providers/theme-provider'; -import { cn } from '@/lib/utils'; -import TanstackProvider from '@/components/providers/tanstack-provider'; -import { Toaster } from '@/components/ui/toaster'; -import { SocketProvider } from '@/lib/services/realtime/socket-provider'; +import { TRPCReactProvider } from "@/trpc/react"; -const font = Sanchez({ subsets: ['latin'], weight: '400' }); +const inter = Inter({ + subsets: ["latin"], + variable: "--font-sans", +}); -export const metadata: Metadata = { - title: 'ParentGrine Falcon', - description: 'Laser focused on your kids', - manifest: '/site.webmanifest', - icons: { - icon: '/favicon.ico', - }, +export const metadata = { + title: "Create T3 App", + description: "Generated by create-t3-app", + icons: [{ rel: "icon", url: "/favicon.ico" }], }; export default function RootLayout({ @@ -29,31 +22,12 @@ export default function RootLayout({ children: React.ReactNode; }) { return ( - - - - - - + + + {children} - - - - - + + ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 00d8fff..d476298 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,103 +1,82 @@ -import React from 'react' -import { signIn } from 'next-auth/react' -import { Button, buttonVariants } from '@/components/ui/button' -import { Icons } from '@/components/icons' -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' -import Link from 'next/link' -import { cn } from '@/lib/utils' +import Link from "next/link"; + +import { CreatePost } from "@/app/_components/create-post"; +import { getServerAuthSession } from "@/server/auth"; +import { api } from "@/trpc/server"; + +export default async function Home() { + const hello = await api.child.hello.query({ text: "from tRPC" }); + const session = await getServerAuthSession(); -export default function Home() { return ( - <> -
-
-

Track Your Children with Ease

-

- Parentgrine Falcon helps you keep an eye on your loved ones and - ensure their safety. -

- - {"Let's go"} - -
-
- -
-
- - - Real-Time Location Tracking - - -

- Instantly know where your children are at all times with - accurate GPS tracking. -

-
-
- - - Geofencing Alerts - - -

- Receive notifications when your child enters or leaves - designated safe zones. -

-
-
- - - Activity Monitoring - - -

- { - "View your child's activity history, including visited places and routes taken." - } -

-
-
-
-
-
-
-

- Keep Your Children Safe Today! -

-

- Download Parentgrine Falcon now and stay connected with your loved - ones. -

- - - Download Now - -
-
-
-

- An open source experiment from PodNoms - source code available{' '} +

+
+

+ Create T3 App +

+
- here +

First Steps →

+
+ Just the basics - Everything you need to know to set up your + database and authentication. +
-

-
- - ) + +

Documentation →

+
+ Learn more about Create T3 App, the libraries it uses, and how to + deploy it. +
+ + +
+

+ {hello ? hello.greeting : "Loading tRPC query..."} +

+ +
+

+ {session && Logged in as {session.user?.name}} +

+ + {session ? "Sign out" : "Sign in"} + +
+
+ + + + + ); +} + +async function CrudShowcase() { + const session = await getServerAuthSession(); + if (!session?.user) return null; + + const latestPost = await api.post.getLatest.query(); + + return ( +
+ {latestPost ? ( +

Your most recent post: {latestPost.name}

+ ) : ( +

You have no posts yet.

+ )} + + +
+ ); } diff --git a/src/components/children/add-child-component.tsx b/src/components/children/add-child-component.tsx deleted file mode 100644 index 39876cc..0000000 --- a/src/components/children/add-child-component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'use client'; -import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { Icons } from '../icons'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog'; -import { AddChildForm } from '@/components/forms/add-child-form'; -const AddChildComponent = () => { - return ( - - - - - - - - - ); -}; - -export default AddChildComponent; diff --git a/src/components/children/child-select-list.tsx b/src/components/children/child-select-list.tsx deleted file mode 100644 index d9b3211..0000000 --- a/src/components/children/child-select-list.tsx +++ /dev/null @@ -1,52 +0,0 @@ -'use client' -import React from 'react' -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select' -import axios from 'axios' -import { useQuery } from '@tanstack/react-query' -import { env } from '@/env.mjs' - -const ChildSelectList = () => { - const { data, isLoading, isError } = useQuery({ - queryKey: ['user-children'], - queryFn: async () => { - const { data } = await axios.get( - `${env.NEXT_PUBLIC_BASE_URL}/child`, - { - withCredentials: true, - }, - ) - return data as ChildModel[] - }, - }) - if (isLoading) return
Loading....
- if (isError) return
Error loading
- return ( - - ) -} - -export default ChildSelectList diff --git a/src/components/children/children-filter.tsx b/src/components/children/children-filter.tsx deleted file mode 100644 index 9027f1f..0000000 --- a/src/components/children/children-filter.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import ChildSelectList from './child-select-list' - -import AddChildComponent from './add-child-component' - -const ChildrenFilter = async () => { - return ( -
- - -
- ) -} - -export default ChildrenFilter diff --git a/src/components/children/children-list.tsx b/src/components/children/children-list.tsx deleted file mode 100644 index 0332ff5..0000000 --- a/src/components/children/children-list.tsx +++ /dev/null @@ -1,64 +0,0 @@ -'use client' -import React from 'react' -import axios from 'axios' -import { useQuery } from '@tanstack/react-query' -import { - Table, - TableBody, - TableCaption, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@/components/ui/table' -import { Button } from '@/components/ui/button' -import { Icons } from '../icons' -import ConnectDeviceDialog from './connect-device-dialog' -import { env } from '@/env.mjs' - -const ChildrenList = () => { - const { data, isLoading, isError } = useQuery({ - queryKey: ['user-children'], - queryFn: async () => { - const { data } = await axios.get( - `${env.NEXT_PUBLIC_BASE_URL}/child`, - { - withCredentials: true, - }, - ) - return data as ChildModel[] - }, - }) - if (isLoading) return
Loading....
- if (isError) return
Error loading
- return ( - - Here are your children. - - - Name - Last seen at - Actions - - - - {data?.map((child) => ( - - {child.name} - Douglas - -
- - -
-
-
- ))} -
-
- ) -} - -export default ChildrenList diff --git a/src/components/children/connect-device-dialog.tsx b/src/components/children/connect-device-dialog.tsx deleted file mode 100644 index 6f1fa60..0000000 --- a/src/components/children/connect-device-dialog.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import { Button } from '@/components/ui/button'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog'; - -import { Icons } from '@/components/icons'; -import QRCode from 'react-qr-code'; - -type ConnectDeviceDialogProps = { - child: ChildModel; -}; - -const ConnectDeviceDialog: React.FC = ({ child }) => { - return ( - - - - - - - Connect new device - - {`Scan this barcode on ${child.name}'s device`} - - -
-
- -
-
- - - -
-
- ); -}; - -export default ConnectDeviceDialog; diff --git a/src/components/forms/add-child-form.tsx b/src/components/forms/add-child-form.tsx deleted file mode 100644 index af4ce9a..0000000 --- a/src/components/forms/add-child-form.tsx +++ /dev/null @@ -1,125 +0,0 @@ -'use client'; - -import * as React from 'react'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; -import * as z from 'zod'; - -import { cn } from '@/lib/utils'; -import { newChildSchema } from '@/lib/validations/child'; -import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { toast } from '@/components/ui/use-toast'; -import { Icons } from '@/components/icons'; -import { DialogFooter } from '../ui/dialog'; -import { useQueryClient, useMutation } from '@tanstack/react-query'; -import axios from 'axios'; -import { - DialogDescription, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; -interface AddChildFormProps extends React.HTMLAttributes {} - -type FormData = z.infer; - -export function AddChildForm({ className, ...props }: AddChildFormProps) { - const [PIN, setPIN] = React.useState(''); - const queryClient = useQueryClient(); - const { mutate: submitNewChild, isPending } = useMutation({ - mutationFn: async (name: string) => - await axios.post('/api/child/create', { name }), - onSuccess: (e) => { - console.log('add-child-form', 'onSuccess', e); - toast({ description: 'Added new child' }); - queryClient.invalidateQueries({ queryKey: ['user-children'] }); - setPIN(e.data.pin); - }, - onError: () => { - toast({ description: 'Something went wrong', variant: 'destructive' }); - }, - }); - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - resolver: zodResolver(newChildSchema), - }); - - async function onSubmit(data: FormData) { - submitNewChild(data.name); - } - - if (PIN) { - return ( - <> - Successfully added child -
- {`Your child's PIN is ${PIN}`} - -
- - ); - } - return ( -
- - Add Child - - { - "Enter your child's details below and press save, then use the displayed PIN to register their device." - } - - -
-
-
- - - {errors?.name && ( -

{errors.name.message}

- )} -
-
-
- - - -
-
-
- ); -} diff --git a/src/components/forms/user-auth-form.tsx b/src/components/forms/user-auth-form.tsx deleted file mode 100644 index 749f575..0000000 --- a/src/components/forms/user-auth-form.tsx +++ /dev/null @@ -1,128 +0,0 @@ -'use client' - -import * as React from 'react' -import { redirect, useSearchParams } from 'next/navigation' -import { zodResolver } from '@hookform/resolvers/zod' -import { signIn } from 'next-auth/react' -import { useForm } from 'react-hook-form' -import * as z from 'zod' - -import { cn } from '@/lib/utils' -import { userAuthSchema } from '@/lib/validations/auth' -import { buttonVariants } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { toast } from '@/components/ui/use-toast' -import { Icons } from '@/components/icons' - -interface UserAuthFormProps extends React.HTMLAttributes {} - -type FormData = z.infer - -export function UserAuthForm({ className, ...props }: UserAuthFormProps) { - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - resolver: zodResolver(userAuthSchema), - }) - const [isLoading, setIsLoading] = React.useState(false) - const [isGoogleLoading, setIsGoogleLoading] = React.useState(false) - const searchParams = useSearchParams() - - async function onSubmit(data: FormData) { - setIsLoading(true) - - const signInResult = await signIn('email', { - email: data.email.toLowerCase(), - redirect: false, - callbackUrl: searchParams?.get('from') || '/dashboard', - }) - - setIsLoading(false) - - if (!signInResult?.ok) { - return toast({ - title: 'Something went wrong.', - description: 'Your sign in request failed. Please try again.', - variant: 'destructive', - }) - } - - return toast({ - title: 'Check your email', - description: 'We sent you a login link. Be sure to check your spam too.', - }) - } - - return ( -
-
-
-
- - - {errors?.email && ( -

- {errors.email.message} -

- )} -
- -
-
-
-
- -
-
- - Or continue with - -
-
- -
- ) -} diff --git a/src/components/header/auth-header.tsx b/src/components/header/auth-header.tsx deleted file mode 100644 index b536e8c..0000000 --- a/src/components/header/auth-header.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React from 'react'; -import { Button, buttonVariants } from '@/components/ui/button'; -import { signIn, signOut, useSession } from 'next-auth/react'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from '@/components/ui/dropdown-menu'; -import { UserAvatar } from '@/components/widgets/user-avatar'; -import Link from 'next/link'; -import { cn } from '@/lib/utils'; -import { Icons } from '../icons'; - -const AuthHeader = () => { - const { data: session, status } = useSession(); - if (status === 'loading') return null; - return !session ? ( - - - Login - - ) : ( - - - - - -
-
- {session?.user?.name && ( -

{session?.user?.name}

- )} - {session?.user?.email && ( -

- {session?.user?.email} -

- )} -
-
- - - Dashboard - - - Billing - - - Settings - - - { - event.preventDefault(); - signOut({ - callbackUrl: `${window.location.origin}`, - }); - }} - > - Sign out - -
-
- ); -}; - -export default AuthHeader; diff --git a/src/components/header/site-header.tsx b/src/components/header/site-header.tsx deleted file mode 100644 index 29bab7f..0000000 --- a/src/components/header/site-header.tsx +++ /dev/null @@ -1,60 +0,0 @@ -'use client'; -import Link from 'next/link'; - -import { siteConfig } from '@/config/site'; -import { buttonVariants } from '@/components/ui/button'; -import { Icons } from '@/components/icons'; -import { MainNav } from '@/components/main-nav'; -import { ThemeToggle } from '@/components/header/theme-toggle'; -import { useSession } from 'next-auth/react'; -import AuthHeader from '@/components/header/auth-header'; -import PresenceIndicator from '@/components/widgets/presence-indicator'; - -export function SiteHeader() { - const { data: session, status } = useSession(); - return ( -
-
- -
- -
-
-
- ); -} diff --git a/src/components/header/theme-toggle.tsx b/src/components/header/theme-toggle.tsx deleted file mode 100644 index c97135e..0000000 --- a/src/components/header/theme-toggle.tsx +++ /dev/null @@ -1,23 +0,0 @@ -'use client' - -import * as React from 'react' -import { Moon, Sun } from 'lucide-react' -import { useTheme } from 'next-themes' - -import { Button } from '@/components/ui/button' - -export function ThemeToggle() { - const { setTheme, theme } = useTheme() - - return ( - - ) -} diff --git a/src/components/icons.tsx b/src/components/icons.tsx deleted file mode 100644 index bd5ae00..0000000 --- a/src/components/icons.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { - ChevronLeft, - ChevronRight, - LucideIcon, - LucideProps, - TabletSmartphone, - Loader2, - Moon, - PlusCircle, - SunMedium, - Twitter, - User, - Rocket, - PlusCircleIcon, - PlusIcon, - LogIn, - Save, - Copy, - Cable, - Edit, - Edit2, Radar, -} from 'lucide-react'; - -export type Icon = LucideIcon; - -export const Icons = { - add: PlusIcon, - chevronLeft: ChevronLeft, - connect: Cable, - chevronRight: ChevronRight, - copy: Copy, - edit: Edit, - sun: SunMedium, - login: LogIn, - mobile: TabletSmartphone, - moon: Moon, - presence: Radar, - rocket: Rocket, - save: Save, - spinner: Loader2, - twitter: Twitter, - user: User, - logo: (props: LucideProps) => ( - - - - ), - gitHub: (props: LucideProps) => ( - - - - ), - google: (props: LucideProps) => ( - - - - ), -}; diff --git a/src/components/main-nav.tsx b/src/components/main-nav.tsx deleted file mode 100644 index dadf2a9..0000000 --- a/src/components/main-nav.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import Link from 'next/link'; - -import { NavItem } from '@/types/nav'; -import { siteConfig } from '@/config/site'; -import { cn } from '@/lib/utils'; -import { Icons } from '@/components/icons'; - -interface MainNavProps { - items?: NavItem[]; -} - -export function MainNav({ items }: MainNavProps) { - return ( -
- - - {siteConfig.name} - - {items?.length ? ( - - ) : null} -
- ); -} diff --git a/src/components/maps/main-map.tsx b/src/components/maps/main-map.tsx deleted file mode 100644 index c3e9d94..0000000 --- a/src/components/maps/main-map.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client'; -import 'leaflet/dist/leaflet.css'; -import React, { useEffect, useState } from 'react'; -import { MapContainer, Marker, Popup, TileLayer, Circle } from 'react-leaflet'; -import { usePingSocket } from '@/lib/hooks/use-ping-socket'; - -const fillBlueOptions = { fillColor: 'blue' }; -const MainMap = () => { - const [isMounted, setIsMounted] = useState(false); - useEffect(() => { - setIsMounted(true); - }, []); - //TODO: Replace with actual childId - usePingSocket({ - childId: 'adeedf73-8068-442e-a9ed-144e18af34a4', - locationUpdate: (location) => { - console.log('MainMap', 'locationUpdate', location); - }, - }); - return ( - isMounted && ( -
- - - - - A pretty CSS3 popup.
Easily customizable. -
-
-
-
- ) - ); -}; - -export default MainMap; diff --git a/src/components/providers/tanstack-provider.tsx b/src/components/providers/tanstack-provider.tsx deleted file mode 100644 index d4ca177..0000000 --- a/src/components/providers/tanstack-provider.tsx +++ /dev/null @@ -1,15 +0,0 @@ -'use client'; -import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; -import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; -import React from 'react'; -const TanstackProvider = ({ children }: { children: React.ReactNode }) => { - const [queryClient] = React.useState(() => new QueryClient()); - return ( - - {children} - - - ); -}; - -export default TanstackProvider; diff --git a/src/components/providers/theme-provider.tsx b/src/components/providers/theme-provider.tsx deleted file mode 100644 index d4b4bbf..0000000 --- a/src/components/providers/theme-provider.tsx +++ /dev/null @@ -1,9 +0,0 @@ -'use client' - -import * as React from 'react' -import { ThemeProvider as NextThemesProvider } from 'next-themes' -import { type ThemeProviderProps } from 'next-themes/dist/types' - -export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children} -} diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx deleted file mode 100644 index 937620a..0000000 --- a/src/components/ui/accordion.tsx +++ /dev/null @@ -1,60 +0,0 @@ -"use client" - -import * as React from "react" -import * as AccordionPrimitive from "@radix-ui/react-accordion" -import { ChevronDown } from "lucide-react" - -import { cn } from "@/lib/utils" - -const Accordion = AccordionPrimitive.Root - -const AccordionItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AccordionItem.displayName = "AccordionItem" - -const AccordionTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - svg]:rotate-180", - className - )} - {...props} - > - {children} - - - -)) -AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName - -const AccordionContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -
{children}
-
-)) -AccordionContent.displayName = AccordionPrimitive.Content.displayName - -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx deleted file mode 100644 index c7925a0..0000000 --- a/src/components/ui/alert-dialog.tsx +++ /dev/null @@ -1,141 +0,0 @@ -"use client" - -import * as React from "react" -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" - -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" - -const AlertDialog = AlertDialogPrimitive.Root - -const AlertDialogTrigger = AlertDialogPrimitive.Trigger - -const AlertDialogPortal = AlertDialogPrimitive.Portal - -const AlertDialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -)) -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName - -const AlertDialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - - -)) -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName - -const AlertDialogHeader = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-) -AlertDialogHeader.displayName = "AlertDialogHeader" - -const AlertDialogFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-) -AlertDialogFooter.displayName = "AlertDialogFooter" - -const AlertDialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName - -const AlertDialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogDescription.displayName = - AlertDialogPrimitive.Description.displayName - -const AlertDialogAction = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName - -const AlertDialogCancel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName - -export { - AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, - AlertDialogTrigger, - AlertDialogContent, - AlertDialogHeader, - AlertDialogFooter, - AlertDialogTitle, - AlertDialogDescription, - AlertDialogAction, - AlertDialogCancel, -} diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx deleted file mode 100644 index 41fa7e0..0000000 --- a/src/components/ui/alert.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const alertVariants = cva( - "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", - { - variants: { - variant: { - default: "bg-background text-foreground", - destructive: - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -const Alert = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & VariantProps ->(({ className, variant, ...props }, ref) => ( -
-)) -Alert.displayName = "Alert" - -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -AlertTitle.displayName = "AlertTitle" - -const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -AlertDescription.displayName = "AlertDescription" - -export { Alert, AlertTitle, AlertDescription } diff --git a/src/components/ui/aspect-ratio.tsx b/src/components/ui/aspect-ratio.tsx deleted file mode 100644 index d6a5226..0000000 --- a/src/components/ui/aspect-ratio.tsx +++ /dev/null @@ -1,7 +0,0 @@ -"use client" - -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" - -const AspectRatio = AspectRatioPrimitive.Root - -export { AspectRatio } diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx deleted file mode 100644 index 51e507b..0000000 --- a/src/components/ui/avatar.tsx +++ /dev/null @@ -1,50 +0,0 @@ -"use client" - -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" - -import { cn } from "@/lib/utils" - -const Avatar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -Avatar.displayName = AvatarPrimitive.Root.displayName - -const AvatarImage = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName - -const AvatarFallback = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName - -export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx deleted file mode 100644 index f000e3e..0000000 --- a/src/components/ui/badge.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", - { - variants: { - variant: { - default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", - secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: - "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -export interface BadgeProps - extends React.HTMLAttributes, - VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return ( -
- ) -} - -export { Badge, badgeVariants } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx deleted file mode 100644 index ac8e0c9..0000000 --- a/src/components/ui/button.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) - -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean -} - -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" - -export { Button, buttonVariants } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx deleted file mode 100644 index 6af8f10..0000000 --- a/src/components/ui/calendar.tsx +++ /dev/null @@ -1,64 +0,0 @@ -"use client" - -import * as React from "react" -import { ChevronLeft, ChevronRight } from "lucide-react" -import { DayPicker } from "react-day-picker" - -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" - -export type CalendarProps = React.ComponentProps - -function Calendar({ - className, - classNames, - showOutsideDays = true, - ...props -}: CalendarProps) { - return ( - , - IconRight: ({ ...props }) => , - }} - {...props} - /> - ) -} -Calendar.displayName = "Calendar" - -export { Calendar } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx deleted file mode 100644 index afa13ec..0000000 --- a/src/components/ui/card.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -const Card = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -Card.displayName = "Card" - -const CardHeader = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardHeader.displayName = "CardHeader" - -const CardTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardTitle.displayName = "CardTitle" - -const CardDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardDescription.displayName = "CardDescription" - -const CardContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)) -CardContent.displayName = "CardContent" - -const CardFooter = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardFooter.displayName = "CardFooter" - -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx deleted file mode 100644 index df61a13..0000000 --- a/src/components/ui/checkbox.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client" - -import * as React from "react" -import * as CheckboxPrimitive from "@radix-ui/react-checkbox" -import { Check } from "lucide-react" - -import { cn } from "@/lib/utils" - -const Checkbox = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - - - -)) -Checkbox.displayName = CheckboxPrimitive.Root.displayName - -export { Checkbox } diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx deleted file mode 100644 index 9fa4894..0000000 --- a/src/components/ui/collapsible.tsx +++ /dev/null @@ -1,11 +0,0 @@ -"use client" - -import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" - -const Collapsible = CollapsiblePrimitive.Root - -const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger - -const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent - -export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx deleted file mode 100644 index 6e83af0..0000000 --- a/src/components/ui/command.tsx +++ /dev/null @@ -1,155 +0,0 @@ -"use client" - -import * as React from "react" -import { DialogProps } from "@radix-ui/react-dialog" -import { Command as CommandPrimitive } from "cmdk" -import { Search } from "lucide-react" - -import { cn } from "@/lib/utils" -import { Dialog, DialogContent } from "@/components/ui/dialog" - -const Command = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -Command.displayName = CommandPrimitive.displayName - -interface CommandDialogProps extends DialogProps {} - -const CommandDialog = ({ children, ...props }: CommandDialogProps) => { - return ( - - - - {children} - - - - ) -} - -const CommandInput = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( -
- - -
-)) - -CommandInput.displayName = CommandPrimitive.Input.displayName - -const CommandList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandList.displayName = CommandPrimitive.List.displayName - -const CommandEmpty = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->((props, ref) => ( - -)) - -CommandEmpty.displayName = CommandPrimitive.Empty.displayName - -const CommandGroup = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandGroup.displayName = CommandPrimitive.Group.displayName - -const CommandSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName - -const CommandItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandItem.displayName = CommandPrimitive.Item.displayName - -const CommandShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -CommandShortcut.displayName = "CommandShortcut" - -export { - Command, - CommandDialog, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - CommandShortcut, - CommandSeparator, -} diff --git a/src/components/ui/context-menu.tsx b/src/components/ui/context-menu.tsx deleted file mode 100644 index 93ef37b..0000000 --- a/src/components/ui/context-menu.tsx +++ /dev/null @@ -1,200 +0,0 @@ -"use client" - -import * as React from "react" -import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" -import { Check, ChevronRight, Circle } from "lucide-react" - -import { cn } from "@/lib/utils" - -const ContextMenu = ContextMenuPrimitive.Root - -const ContextMenuTrigger = ContextMenuPrimitive.Trigger - -const ContextMenuGroup = ContextMenuPrimitive.Group - -const ContextMenuPortal = ContextMenuPrimitive.Portal - -const ContextMenuSub = ContextMenuPrimitive.Sub - -const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup - -const ContextMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)) -ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName - -const ContextMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName - -const ContextMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName - -const ContextMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName - -const ContextMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)) -ContextMenuCheckboxItem.displayName = - ContextMenuPrimitive.CheckboxItem.displayName - -const ContextMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName - -const ContextMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName - -const ContextMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName - -const ContextMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -ContextMenuShortcut.displayName = "ContextMenuShortcut" - -export { - ContextMenu, - ContextMenuTrigger, - ContextMenuContent, - ContextMenuItem, - ContextMenuCheckboxItem, - ContextMenuRadioItem, - ContextMenuLabel, - ContextMenuSeparator, - ContextMenuShortcut, - ContextMenuGroup, - ContextMenuPortal, - ContextMenuSub, - ContextMenuSubContent, - ContextMenuSubTrigger, - ContextMenuRadioGroup, -} diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx deleted file mode 100644 index 47ce215..0000000 --- a/src/components/ui/dialog.tsx +++ /dev/null @@ -1,119 +0,0 @@ -"use client" - -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { X } from "lucide-react" - -import { cn } from "@/lib/utils" - -const Dialog = DialogPrimitive.Root - -const DialogTrigger = DialogPrimitive.Trigger - -const DialogPortal = DialogPrimitive.Portal - -const DialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName - -const DialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - {children} - - - Close - - - -)) -DialogContent.displayName = DialogPrimitive.Content.displayName - -const DialogHeader = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-) -DialogHeader.displayName = "DialogHeader" - -const DialogFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-) -DialogFooter.displayName = "DialogFooter" - -const DialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName - -const DialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName - -export { - Dialog, - DialogPortal, - DialogOverlay, - DialogTrigger, - DialogContent, - DialogHeader, - DialogFooter, - DialogTitle, - DialogDescription, -} diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx deleted file mode 100644 index f69a0d6..0000000 --- a/src/components/ui/dropdown-menu.tsx +++ /dev/null @@ -1,200 +0,0 @@ -"use client" - -import * as React from "react" -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" -import { Check, ChevronRight, Circle } from "lucide-react" - -import { cn } from "@/lib/utils" - -const DropdownMenu = DropdownMenuPrimitive.Root - -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger - -const DropdownMenuGroup = DropdownMenuPrimitive.Group - -const DropdownMenuPortal = DropdownMenuPrimitive.Portal - -const DropdownMenuSub = DropdownMenuPrimitive.Sub - -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup - -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)) -DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName - -const DropdownMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName - -const DropdownMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)) -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName - -const DropdownMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName - -const DropdownMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName - -const DropdownMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName - -const DropdownMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName - -const DropdownMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -DropdownMenuShortcut.displayName = "DropdownMenuShortcut" - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuRadioItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuRadioGroup, -} diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx deleted file mode 100644 index 4603f8b..0000000 --- a/src/components/ui/form.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { Slot } from "@radix-ui/react-slot" -import { - Controller, - ControllerProps, - FieldPath, - FieldValues, - FormProvider, - useFormContext, -} from "react-hook-form" - -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" - -const Form = FormProvider - -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath -> = { - name: TName -} - -const FormFieldContext = React.createContext( - {} as FormFieldContextValue -) - -const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath ->({ - ...props -}: ControllerProps) => { - return ( - - - - ) -} - -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState, formState } = useFormContext() - - const fieldState = getFieldState(fieldContext.name, formState) - - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } - - const { id } = itemContext - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} - -type FormItemContextValue = { - id: string -} - -const FormItemContext = React.createContext( - {} as FormItemContextValue -) - -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId() - - return ( - -
- - ) -}) -FormItem.displayName = "FormItem" - -const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField() - - return ( -