diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 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/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e2455b1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/sern-bin.iml b/.idea/sern-bin.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/sern-bin.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/drizzle/0000_ambiguous_mach_iv.sql b/drizzle/0000_ambiguous_mach_iv.sql new file mode 100644 index 0000000..ed83776 --- /dev/null +++ b/drizzle/0000_ambiguous_mach_iv.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS "code" ( + "id" text PRIMARY KEY NOT NULL, + "code" text NOT NULL, + "lang" text NOT NULL, + "authorId" text NOT NULL +); diff --git a/drizzle/0001_complete_master_chief.sql b/drizzle/0001_complete_master_chief.sql new file mode 100644 index 0000000..b2190ad --- /dev/null +++ b/drizzle/0001_complete_master_chief.sql @@ -0,0 +1 @@ +ALTER TABLE "code" ADD COLUMN "fileName" text NOT NULL; \ No newline at end of file diff --git a/drizzle/0002_lovely_inhumans.sql b/drizzle/0002_lovely_inhumans.sql new file mode 100644 index 0000000..ab30a3b --- /dev/null +++ b/drizzle/0002_lovely_inhumans.sql @@ -0,0 +1 @@ +ALTER TABLE "code" ADD COLUMN "description" text NOT NULL; \ No newline at end of file diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..72500b7 --- /dev/null +++ b/drizzle/meta/0000_snapshot.json @@ -0,0 +1,49 @@ +{ + "id": "4402c683-875f-4d90-a284-660e23a1a83d", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "5", + "dialect": "pg", + "tables": { + "code": { + "name": "code", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lang": { + "name": "lang", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authorId": { + "name": "authorId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..734d0ff --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,55 @@ +{ + "id": "ae876484-7aa1-4b33-bf67-b322a3ef4a0d", + "prevId": "4402c683-875f-4d90-a284-660e23a1a83d", + "version": "5", + "dialect": "pg", + "tables": { + "code": { + "name": "code", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fileName": { + "name": "fileName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lang": { + "name": "lang", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authorId": { + "name": "authorId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0002_snapshot.json b/drizzle/meta/0002_snapshot.json new file mode 100644 index 0000000..1c304c0 --- /dev/null +++ b/drizzle/meta/0002_snapshot.json @@ -0,0 +1,61 @@ +{ + "id": "ac31cb3c-c01e-480d-bfeb-4eee84014495", + "prevId": "ae876484-7aa1-4b33-bf67-b322a3ef4a0d", + "version": "5", + "dialect": "pg", + "tables": { + "code": { + "name": "code", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fileName": { + "name": "fileName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lang": { + "name": "lang", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authorId": { + "name": "authorId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json new file mode 100644 index 0000000..e7e9b2d --- /dev/null +++ b/drizzle/meta/_journal.json @@ -0,0 +1,27 @@ +{ + "version": "5", + "dialect": "pg", + "entries": [ + { + "idx": 0, + "version": "5", + "when": 1705152102873, + "tag": "0000_ambiguous_mach_iv", + "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1705163965392, + "tag": "0001_complete_master_chief", + "breakpoints": true + }, + { + "idx": 2, + "version": "5", + "when": 1705241267004, + "tag": "0002_lovely_inhumans", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 751856b..52eff32 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,42 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "migrate": "yarn generateMigrations && node --loader ts-node/esm src/db/migrations.mts", + "generateMigrations": "drizzle-kit generate:pg --schema ./src/db/schema.ts" }, "dependencies": { + "@clerk/nextjs": "^4.29.3", + "@mantine/core": "^7.4.1", + "@mantine/hooks": "^7.4.1", + "@mantine/notifications": "^7.4.1", + "@monaco-editor/react": "^4.6.0", + "bottleneck": "^2.19.5", + "clsx": "^2.1.0", + "dotenv": "^16.3.1", + "drizzle-orm": "^0.29.3", + "lru-cache": "^10.1.0", + "next": "14.0.4", + "next-nprogress-bar": "^2.1.2", + "postgres": "^3.4.3", "react": "^18", "react-dom": "^18", - "next": "14.0.4" + "react-icons": "^5.0.1", + "util-utils": "^1.0.3", + "zod": "^3.22.4", + "zustand": "^4.4.7" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "drizzle-kit": "^0.20.12", "eslint": "^8", - "eslint-config-next": "14.0.4" + "eslint-config-next": "14.0.4", + "postcss": "^8.4.33", + "postcss-preset-mantine": "^1.12.3", + "postcss-simple-vars": "^7.0.1", + "ts-node": "^10.9.2", + "typescript": "^5" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..13ed8b0 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,14 @@ +module.exports = { + plugins: { + 'postcss-preset-mantine': {}, + 'postcss-simple-vars': { + variables: { + 'mantine-breakpoint-xs': '36em', + 'mantine-breakpoint-sm': '48em', + 'mantine-breakpoint-md': '62em', + 'mantine-breakpoint-lg': '75em', + 'mantine-breakpoint-xl': '88em', + }, + }, + }, +}; \ No newline at end of file diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..553109c Binary files /dev/null and b/public/logo.png differ diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index d4f491e..6605fea 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,107 +1,5 @@ :root { - --max-width: 1100px; - --border-radius: 12px; --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; - - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; - - --primary-glow: conic-gradient( - from 180deg at 50% 50%, - #16abff33 0deg, - #0885ff33 55deg, - #54d6ff33 120deg, - #0071ff33 160deg, - transparent 360deg - ); - --secondary-glow: radial-gradient( - rgba(255, 255, 255, 1), - rgba(255, 255, 255, 0) - ); - - --tile-start-rgb: 239, 245, 249; - --tile-end-rgb: 228, 232, 233; - --tile-border: conic-gradient( - #00000080, - #00000040, - #00000030, - #00000020, - #00000010, - #00000010, - #00000080 - ); - - --callout-rgb: 238, 240, 241; - --callout-border-rgb: 172, 175, 176; - --card-rgb: 180, 185, 188; - --card-border-rgb: 131, 134, 135; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - - --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); - --secondary-glow: linear-gradient( - to bottom right, - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0.3) - ); - - --tile-start-rgb: 2, 13, 46; - --tile-end-rgb: 2, 5, 19; - --tile-border: conic-gradient( - #ffffff80, - #ffffff40, - #ffffff30, - #ffffff20, - #ffffff10, - #ffffff10, - #ffffff80 - ); - - --callout-rgb: 20, 20, 20; - --callout-border-rgb: 108, 108, 108; - --card-rgb: 100, 100, 100; - --card-border-rgb: 200, 200, 200; - } -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - -a { - color: inherit; - text-decoration: none; -} - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 40e027f..c03ee99 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,12 +1,19 @@ import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' +import {ClerkLoaded, ClerkLoading, ClerkProvider} from "@clerk/nextjs"; +import {ColorSchemeScript, LoadingOverlay, MantineProvider} from '@mantine/core'; +import {Notifications} from "@mantine/notifications"; +import '@mantine/core/styles.css'; +import '@mantine/notifications/styles.css'; +import Providers from "@/providers"; +import NavBar from "@/components/NavBar/NavBar"; const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', + title: 'sern bin', + description: 'A sern-centric snippet sharing platform' } export default function RootLayout({ @@ -15,8 +22,29 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - - {children} - + + + + + + + + + + + + + + + +
+ {children} +
+
+
+
+ + +
) } diff --git a/src/app/me/page.tsx b/src/app/me/page.tsx new file mode 100644 index 0000000..303db72 --- /dev/null +++ b/src/app/me/page.tsx @@ -0,0 +1,7 @@ +export default function Page() { + return ( +
+

Sorry, but this is WIP right now!

+
+ ) +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 657e775..8b9c16e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,95 +1,8 @@ -import Image from 'next/image' -import styles from './page.module.css' +import {auth} from "@clerk/nextjs"; +import CreateSnippet from "@/components/CreateSnippet/CreateSnippet"; +import SignInPrompt from "@/components/SignInPrompt/SignInPrompt"; export default function Home() { - return ( -
-
-

- Get started by editing  - src/app/page.tsx -

-
- - By{' '} - Vercel Logo - -
-
- -
- Next.js Logo -
- -
- -

- Docs -> -

-

Find in-depth information about Next.js features and API.

-
- - -

- Learn -> -

-

Learn about Next.js in an interactive course with quizzes!

-
- - -

- Templates -> -

-

Explore starter templates for Next.js.

-
- - -

- Deploy -> -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-
-
-
- ) + const { userId } = auth() + return userId ? : } diff --git a/src/app/s/[id]/index.css b/src/app/s/[id]/index.css new file mode 100644 index 0000000..b76a9ef --- /dev/null +++ b/src/app/s/[id]/index.css @@ -0,0 +1,7 @@ +.snippetDescription h1, p { + margin: 0; +} + +.snippetDescription p:last-of-type { + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/app/s/[id]/page.tsx b/src/app/s/[id]/page.tsx new file mode 100644 index 0000000..43f4a41 --- /dev/null +++ b/src/app/s/[id]/page.tsx @@ -0,0 +1,29 @@ +import './index.css' +import db from '@/db/index' +import * as schema from '@/db/schema' +import {eq} from "drizzle-orm"; +import {redirect} from "next/navigation"; +import {clerkClient} from "@clerk/nextjs"; +import MonacoEditor from "@/components/MonacoEditor/MonacoEditor"; + +export default async function Page({ params }: { params: { id: string } }) { + const query = await db.query.code.findFirst({ + where: eq(schema.code.id, params.id) + }).execute() + if (!query) { + redirect('/s-notfound') + } + + const user = await clerkClient.users.getUser(query.authorId) + return ( +
+
+
+

File {query.fileName} by {user.username}

+
+

Description: {query.description}

+
+ +
+ ) +} \ No newline at end of file diff --git a/src/components/CreateSnippet/CreateSnippet.tsx b/src/components/CreateSnippet/CreateSnippet.tsx new file mode 100644 index 0000000..5e110c4 --- /dev/null +++ b/src/components/CreateSnippet/CreateSnippet.tsx @@ -0,0 +1,79 @@ +'use client' + +import {Button, Select, TextInput} from "@mantine/core"; +import MonacoEditor from "@/components/MonacoEditor/MonacoEditor"; +import { useRouter } from "next-nprogress-bar"; +import {useUser} from "@clerk/nextjs"; +import {useEffect, useState} from "react"; +import {ICreateApiRequest} from "@/utils/types"; +import {notifications} from "@mantine/notifications"; +import {createSnippet} from "@/components/CreateSnippet/createSnippet"; +import styles from './index.module.css'; + +export default function CreateSnippet() { + const user = useUser().user! + const router = useRouter() + const [buttonLoading, setButtonLoading] = useState(false) + const [editorText, setEditorText] = useState('') + const [snippet, setSnippet] = useState({ + fileName: '', + description: '', + authorId: user.id, + lang: 'typescript', + code: '' + }) + + useEffect(() => { + setSnippet({ ...snippet, code: editorText }) + console.log(snippet) + }, [editorText]); + return ( +
+
+ setSnippet({ ...snippet, fileName: ev.currentTarget.value })} + /> + setSnippet({ ...snippet, description: ev.currentTarget.value })} + /> +