diff --git a/.gitignore b/.gitignore index fd3dbb5..7e43796 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /.pnp .pnp.js .yarn/install-state.gz +.env # testing /coverage diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..74fb772 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +# syntax=docker/dockerfile:1 + +FROM node:18.17.0-bullseye + +WORKDIR /app + +EXPOSE 3000 + +COPY . . + +RUN npm install + +CMD ["npm", "run", "dev"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..707c3fe --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3" +services: + db: + container_name: plebdevs-db + image: postgres:13.2 + restart: always + expose: + - "5432" + ports: + - "5432:5432" + env_file: + - .env + volumes: + - postgres_data:/var/lib/postgresql/data + app: + container_name: plebdevs + build: . + depends_on: + - db + env_file: + - .env + ports: + - "3000:3000" + links: + - db + +volumes: + postgres_data: diff --git a/package-lock.json b/package-lock.json index 966c3a3..005965a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "next": "14.0.4", + "primeicons": "^6.0.1", + "primereact": "^10.2.1", "react": "^18", "react-dom": "^18" }, @@ -30,7 +32,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -331,6 +332,34 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + }, + "node_modules/@types/react": { + "version": "18.2.45", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", + "integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, "node_modules/@typescript-eslint/parser": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", @@ -830,6 +859,11 @@ "node": ">= 8" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -923,6 +957,15 @@ "node": ">=6.0.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2550,7 +2593,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2827,11 +2869,37 @@ "node": ">= 0.8.0" } }, + "node_modules/primeicons": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz", + "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA==" + }, + "node_modules/primereact": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.2.1.tgz", + "integrity": "sha512-F25053E1z+fod6V7AJ1Ix/DwSPkFQotk2+Idm0XkFsN+gQEywH7DgtbvNKpUA+LEq48h2+/WVK3D0V8IAm1Npg==", + "dependencies": { + "@types/react-transition-group": "^4.4.1", + "react-transition-group": "^4.4.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -2893,8 +2961,22 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } }, "node_modules/reflect.getprototypeof": { "version": "1.0.4", @@ -2919,8 +3001,7 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", diff --git a/package.json b/package.json index c3ba939..afbbcbd 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,11 @@ "lint": "next lint" }, "dependencies": { + "next": "14.0.4", + "primeicons": "^6.0.1", + "primereact": "^10.2.1", "react": "^18", - "react-dom": "^18", - "next": "14.0.4" + "react-dom": "^18" }, "devDependencies": { "eslint": "^8", diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..85733f7 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,56 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model User { + id Int @id @default(autoincrement()) + npub String @unique + username String? @unique + purchased Purchase[] + role Role? @relation(fields: [roleId], references: [id]) + roleId Int? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Role { + id Int @id @default(autoincrement()) + name String @unique + users User[] +} + +model Course { + id Int @id @default(autoincrement()) + title String + description String + isFree Boolean @default(false) + resources Resource[] + purchases Purchase[] + noteId String? @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Resource { + id Int @id @default(autoincrement()) + title String + content String // Markdown content + course Course? @relation(fields: [courseId], references: [id]) + noteId String? @unique + courseId Int? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Purchase { + id Int @id @default(autoincrement()) + user User @relation(fields: [userId], references: [id]) + userId Int + course Course @relation(fields: [courseId], references: [id]) + courseId Int + amountPaid Int // in satoshis + paymentType String // Webln or NWC + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} \ No newline at end of file diff --git a/public/plebdevs-guy.jpg b/public/plebdevs-guy.jpg new file mode 100644 index 0000000..a846e32 Binary files /dev/null and b/public/plebdevs-guy.jpg differ diff --git a/src/components/navbar/Navbar.js b/src/components/navbar/Navbar.js new file mode 100644 index 0000000..b407bcb --- /dev/null +++ b/src/components/navbar/Navbar.js @@ -0,0 +1,36 @@ +import React from 'react'; +import Image from 'next/image'; +import { Button } from 'primereact/button'; +import { Menubar } from 'primereact/menubar'; +import 'primereact/resources/primereact.min.css'; // core css +import 'primeicons/primeicons.css'; // icons +import styles from './navbar.module.css'; + +const end = ( +