first commit
This commit is contained in:
parent
dcc30ded70
commit
f72df76a02
@ -2,7 +2,7 @@
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"semi": false,
|
||||
"semi": true,
|
||||
"printWidth": 100,
|
||||
"plugins": [
|
||||
"prettier-plugin-svelte"
|
||||
|
3383
package-lock.json
generated
Normal file
3383
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "sk-prisma-quickstart",
|
||||
"name": "mind.am",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -24,7 +24,7 @@
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"prettier": "^2.8.3",
|
||||
"prettier-plugin-svelte": "^2.9.0",
|
||||
"prisma": "^4.9.0",
|
||||
"prisma": "^4.13.0",
|
||||
"rome": "^11.0.0",
|
||||
"svelte": "^3.55.1",
|
||||
"svelte-check": "^3.0.3",
|
||||
@ -35,10 +35,8 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@lucia-auth/adapter-prisma": "^0.4.0",
|
||||
"@lucia-auth/sveltekit": "^0.6.2",
|
||||
"@picocss/pico": "^1.5.7",
|
||||
"@prisma/client": "^4.9.0",
|
||||
"lucia-auth": "^0.6.0"
|
||||
"@lucia-auth/adapter-prisma": "^1.0.0",
|
||||
"@prisma/client": "^4.13.0",
|
||||
"lucia-auth": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
377
plan.excalidraw
Normal file
377
plan.excalidraw
Normal file
@ -0,0 +1,377 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
|
||||
"elements": [
|
||||
{
|
||||
"type": "text",
|
||||
"version": 210,
|
||||
"versionNonce": 1101517802,
|
||||
"isDeleted": false,
|
||||
"id": "BBh4tqJDdAtmiGS_T9NhB",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 346,
|
||||
"y": 132,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 386.299560546875,
|
||||
"height": 175,
|
||||
"seed": 173011999,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681666786640,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"text": "Main features\n- view tasks in list\n- add tasks\n- filter tasks\n- add events\n- view events on a calendar/time table\n- productivity stats",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Main features\n- view tasks in list\n- add tasks\n- filter tasks\n- add events\n- view events on a calendar/time table\n- productivity stats",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 168
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 68,
|
||||
"versionNonce": 1783641974,
|
||||
"isDeleted": false,
|
||||
"id": "yhIvmdxt78nVjxVMbg817",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 346.42857142857133,
|
||||
"y": 466.7142857142858,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 243.93699645996094,
|
||||
"height": 35,
|
||||
"seed": 145102353,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965824,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "View Tasks in list",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "View Tasks in list",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 25
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 136,
|
||||
"versionNonce": 1209570673,
|
||||
"isDeleted": false,
|
||||
"id": "GJ07SGnaoG015S8qKJLRH",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 359.3078862861435,
|
||||
"y": 545.6229442427883,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 158.20707565456237,
|
||||
"height": 297.1927309024958,
|
||||
"seed": 773169521,
|
||||
"groupIds": [
|
||||
"58NIHvz3-h0w-wpDv2qvX"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681652636015,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 53,
|
||||
"versionNonce": 1166399670,
|
||||
"isDeleted": false,
|
||||
"id": "sgV5gLSoJU8ahlPzVWirQ",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 363.7435986876732,
|
||||
"y": 545.6229442427883,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 148.82061767578125,
|
||||
"height": 35,
|
||||
"seed": 266673009,
|
||||
"groupIds": [
|
||||
"58NIHvz3-h0w-wpDv2qvX"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965826,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Task name",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Task name",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 25
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 293,
|
||||
"versionNonce": 803399999,
|
||||
"isDeleted": false,
|
||||
"id": "Ot3R5vdTppcVPfNkkWKAf",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 744.8648696156656,
|
||||
"y": 546.7515194397288,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 158.20707565456237,
|
||||
"height": 297.1927309024958,
|
||||
"seed": 270974801,
|
||||
"groupIds": [
|
||||
"4ig37QJCWH5WzEsDoZa_9"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681652677439,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 218,
|
||||
"versionNonce": 552187306,
|
||||
"isDeleted": false,
|
||||
"id": "QssO4ADI4QybG77uAi4T5",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 749.3005820171953,
|
||||
"y": 546.7515194397288,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 113.6524658203125,
|
||||
"height": 35,
|
||||
"seed": 2049202751,
|
||||
"groupIds": [
|
||||
"4ig37QJCWH5WzEsDoZa_9"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965826,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Deadline",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Deadline",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 25
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 334,
|
||||
"versionNonce": 1486707231,
|
||||
"isDeleted": false,
|
||||
"id": "3hVNY2-d-wsWmq25MKBJF",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 902.7219496666585,
|
||||
"y": 544.9229530356494,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 84.27853562906617,
|
||||
"height": 297.1927309024958,
|
||||
"seed": 333160465,
|
||||
"groupIds": [
|
||||
"-7vVeIJHP7GrJWtZlI9Qp"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681652691941,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 240,
|
||||
"versionNonce": 66408950,
|
||||
"isDeleted": false,
|
||||
"id": "C0Sl-rFjn7SxXayob92Gz",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 907.1576620681882,
|
||||
"y": 544.9229530356494,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 74.87232971191406,
|
||||
"height": 35,
|
||||
"seed": 1631249791,
|
||||
"groupIds": [
|
||||
"-7vVeIJHP7GrJWtZlI9Qp"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965827,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Check",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Check",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 25
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 329,
|
||||
"versionNonce": 1935340159,
|
||||
"isDeleted": false,
|
||||
"id": "uDpNt6DRsp_-nRDXNaA8k",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 518.2935415340769,
|
||||
"y": 544.9229530356494,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 224.74276167750924,
|
||||
"height": 297.1927309024958,
|
||||
"seed": 1020428785,
|
||||
"groupIds": [
|
||||
"KoZaThEPF0xicVDvsXM6v"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681652674302,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 267,
|
||||
"versionNonce": 1580822634,
|
||||
"isDeleted": false,
|
||||
"id": "OP-njsWFGJLXrTxK6HgOK",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 522.7292539356066,
|
||||
"y": 544.9229530356494,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 214.95692443847656,
|
||||
"height": 35,
|
||||
"seed": 285446559,
|
||||
"groupIds": [
|
||||
"KoZaThEPF0xicVDvsXM6v"
|
||||
],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965828,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Content preview",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Content preview",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 25
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 188,
|
||||
"versionNonce": 1352901430,
|
||||
"isDeleted": false,
|
||||
"id": "rxmez1KN1SGu8hwPP2lre",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 360.7864570866533,
|
||||
"y": 869.4299495544628,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 974.8241577148438,
|
||||
"height": 105,
|
||||
"seed": 558546495,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1681658965829,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Events:\n- Clicking it should bring up a full window showing the full content\n- Pressing check should gray out the task and move it to the bottom",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Events:\n- Clicking it should bring up a full window showing the full content\n- Pressing check should gray out the task and move it to the bottom",
|
||||
"lineHeight": 1.25,
|
||||
"baseline": 95
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": null,
|
||||
"viewBackgroundColor": "#ffffff"
|
||||
},
|
||||
"files": {}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Task" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"content" TEXT,
|
||||
"deadline" TIMESTAMP(3),
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Task_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Event" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"content" TEXT,
|
||||
"length" INTEGER NOT NULL,
|
||||
"start_time" TIMESTAMP(3) NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Event_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "auth_user" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"username" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "auth_user_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "auth_session" (
|
||||
"id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"active_expires" BIGINT NOT NULL,
|
||||
"idle_expires" BIGINT NOT NULL,
|
||||
|
||||
CONSTRAINT "auth_session_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "auth_key" (
|
||||
"primary_id" TEXT NOT NULL,
|
||||
"hashed_password" TEXT,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"primary" BOOLEAN NOT NULL,
|
||||
|
||||
CONSTRAINT "auth_key_pkey" PRIMARY KEY ("primary_id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "auth_user_id_key" ON "auth_user"("id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "auth_user_username_key" ON "auth_user"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "auth_session_id_key" ON "auth_session"("id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "auth_session_user_id_idx" ON "auth_session"("user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "auth_key_primary_id_key" ON "auth_key"("primary_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "auth_key_user_id_idx" ON "auth_key"("user_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Task" ADD CONSTRAINT "Task_userId_fkey" FOREIGN KEY ("userId") REFERENCES "auth_user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Event" ADD CONSTRAINT "Event_userId_fkey" FOREIGN KEY ("userId") REFERENCES "auth_user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "auth_session" ADD CONSTRAINT "auth_session_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth_user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "auth_key" ADD CONSTRAINT "auth_key_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth_user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
@ -6,47 +6,95 @@ generator client {
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = "file:./dev.sqlite"
|
||||
provider = "postgres"
|
||||
url = "postgresql://postgres:b359a3f0b1129da7@141.147.61.193:3021/postgres"
|
||||
}
|
||||
|
||||
model Article {
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
content String
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
model Song {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
image String
|
||||
hasMultipleNELs Boolean
|
||||
neuralEffectLevel Float
|
||||
instrumentations String[]
|
||||
|
||||
genre Genre @relation(fields: [genreId], references: [id])
|
||||
genreId String
|
||||
|
||||
complexityDisplayValue ComplexityLevel
|
||||
neuralEffectLevelDisplayValue NELevel
|
||||
|
||||
usersFavorited AuthUser? @relation(fields: [usersFavoritedId], references: [id])
|
||||
usersFavoritedId String?
|
||||
}
|
||||
|
||||
model User {
|
||||
model MentalState {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
|
||||
genres Genre[]
|
||||
}
|
||||
|
||||
model Genre {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
|
||||
mentalState MentalState[]
|
||||
|
||||
isNature Boolean
|
||||
activities Activity[]
|
||||
Song Song[]
|
||||
}
|
||||
|
||||
model Activity {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
genre Genre @relation(fields: [genreId], references: [id])
|
||||
genreId String
|
||||
}
|
||||
|
||||
model AuthUser {
|
||||
id String @id @unique
|
||||
name String
|
||||
username String @unique
|
||||
articles Article[]
|
||||
session Session[]
|
||||
Key Key[]
|
||||
favorites Song[]
|
||||
auth_session AuthSession[]
|
||||
auth_key AuthKey[]
|
||||
|
||||
@@map("user")
|
||||
@@map("auth_user")
|
||||
}
|
||||
|
||||
model Session {
|
||||
model AuthSession {
|
||||
id String @id @unique
|
||||
user_id String
|
||||
active_expires BigInt
|
||||
idle_expires BigInt
|
||||
user User @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
auth_user AuthUser @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([user_id])
|
||||
@@map("session")
|
||||
@@map("auth_session")
|
||||
}
|
||||
|
||||
model Key {
|
||||
model AuthKey {
|
||||
id String @id @unique
|
||||
hashed_password String?
|
||||
user_id String
|
||||
primary Boolean
|
||||
user User @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
primary_key Boolean
|
||||
expires BigInt?
|
||||
auth_user AuthUser @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([user_id])
|
||||
@@map("key")
|
||||
@@map("auth_key")
|
||||
}
|
||||
|
||||
enum ComplexityLevel {
|
||||
Low
|
||||
Medium
|
||||
High
|
||||
}
|
||||
|
||||
enum NELevel {
|
||||
Low
|
||||
Medium
|
||||
High
|
||||
}
|
||||
|
4
src/app.d.ts
vendored
4
src/app.d.ts
vendored
@ -4,9 +4,7 @@ declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
interface Locals {
|
||||
validate: import("@lucia-auth/sveltekit").Validate
|
||||
validateUser: import("@lucia-auth/sveltekit").ValidateUser
|
||||
setSession: import("@lucia-auth/sveltekit").SetSession
|
||||
auth: import("lucia-auth").AuthRequest;
|
||||
}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
|
77
src/app.html
77
src/app.html
@ -5,6 +5,83 @@
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/TTNormsPro-Bold.ttf"
|
||||
as="font"
|
||||
type="font/ttf"
|
||||
crossorigin="anonymous"
|
||||
data-react-helmet="true"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/TTNormsPro-Regular.ttf"
|
||||
as="font"
|
||||
type="font/ttf"
|
||||
crossorigin="anonymous"
|
||||
data-react-helmet="true"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/TTNormsPro-Medium.ttf"
|
||||
as="font"
|
||||
type="font/ttf"
|
||||
crossorigin="anonymous"
|
||||
data-react-helmet="true"
|
||||
/>
|
||||
|
||||
<style data-react-helmet="true">
|
||||
@font-face {
|
||||
font-family: TTNormsPro-Regular;
|
||||
src: url('/fonts/TTNormsPro-Regular.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: TTNormsPro-Medium;
|
||||
src: url('/fonts/TTNormsPro-Medium.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: TTNormsPro-Bold;
|
||||
src: url('/fonts/TTNormsPro-Bold.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
*,
|
||||
::after,
|
||||
::before {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
background: rgb(25, 23, 54);
|
||||
color: white;
|
||||
font-family: Poppins, TTNormsPro-Regular, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { handleHooks } from "@lucia-auth/sveltekit"
|
||||
import { auth } from "$lib/server/lucia"
|
||||
import type { Handle } from "@sveltejs/kit"
|
||||
import { sequence } from "@sveltejs/kit/hooks"
|
||||
@ -7,4 +6,7 @@ export const customHandle: Handle = async ({ resolve, event }) => {
|
||||
return resolve(event)
|
||||
}
|
||||
|
||||
export const handle: Handle = sequence(handleHooks(auth), customHandle)
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
event.locals.auth = auth.handleRequest(event);
|
||||
return await resolve(event);
|
||||
};
|
||||
|
82
src/lib/components/large-button.svelte
Normal file
82
src/lib/components/large-button.svelte
Normal file
@ -0,0 +1,82 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let title = "";
|
||||
export let description = "";
|
||||
export let selected = false;
|
||||
</script>
|
||||
|
||||
<div class="large-button" class:active={selected} on:click={() => dispatch('click')}>
|
||||
<div class="content-wrapper">
|
||||
<h6>{title}</h6>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.large-button.active {
|
||||
opacity: 1;
|
||||
background: rgb(25, 23, 54);
|
||||
}
|
||||
|
||||
.large-button {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 0.5rem;
|
||||
border-radius: 0.75rem;
|
||||
background: rgba(25, 23, 54, 0.5);
|
||||
opacity: 0.5;
|
||||
transition: background 0.2s ease-in-out 0s, opacity 0.2s ease-in-out 0s;
|
||||
min-height: 6rem;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:global(.large-button.active)::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-radius: 0.78rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(100.23deg, rgb(73, 21, 248) -26.81%, rgb(255, 73, 107) 134.77%);
|
||||
opacity: 1;
|
||||
z-index: -1;
|
||||
transition: transform 0.15s ease-in-out 0s;
|
||||
transform: scaleX(1.005) scaleY(1.02);
|
||||
}
|
||||
|
||||
.large-button:hover {
|
||||
background: rgb(37, 35, 64);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-moz-box-pack: start;
|
||||
justify-content: flex-start;
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
||||
.content-wrapper h6 {
|
||||
-moz-box-align: center;
|
||||
align-items: center;
|
||||
font-family: TTNormsPro-Bold;
|
||||
font-size: 1rem;
|
||||
color: rgb(255, 255, 255);
|
||||
display: flex;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.content-wrapper p {
|
||||
margin-top: 0.5rem;
|
||||
font-family: TTNormsPro-Regular;
|
||||
font-size: 0.875rem;
|
||||
color: rgb(212, 210, 234);
|
||||
}
|
||||
</style>
|
67
src/lib/components/large-switch.svelte
Normal file
67
src/lib/components/large-switch.svelte
Normal file
@ -0,0 +1,67 @@
|
||||
<script lang="ts">
|
||||
import Switch from './switch.svelte';
|
||||
|
||||
export let toggled: boolean = false;
|
||||
export let title: String;
|
||||
</script>
|
||||
|
||||
<div class="large-switch" class:active={toggled} on:click={() => (toggled = !toggled)}>
|
||||
<div class="title">{title}</div>
|
||||
|
||||
<Switch {toggled} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.large-switch.active {
|
||||
opacity: 1;
|
||||
background: rgb(25, 23, 54);
|
||||
}
|
||||
|
||||
.large-switch {
|
||||
-moz-box-align: center;
|
||||
align-items: center;
|
||||
background: rgba(25, 23, 54, 0.5);
|
||||
border-radius: 0.75rem;
|
||||
border: medium none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 3.5rem;
|
||||
-moz-box-pack: justify;
|
||||
justify-content: space-between;
|
||||
margin: 0.25rem 0px;
|
||||
opacity: 0.5;
|
||||
outline: none;
|
||||
padding: 0.25rem 1.25rem;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
text-transform: lowercase;
|
||||
transition: background 0.2s ease-in-out 0s, opacity 0.2s ease-in-out 0s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:global(.large-switch.active)::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-radius: 0.78rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(100.23deg, rgb(73, 21, 248) -26.81%, rgb(255, 73, 107) 134.77%);
|
||||
opacity: 1;
|
||||
z-index: -1;
|
||||
transition: transform 0.15s ease-in-out 0s;
|
||||
transform: scaleX(1.005) scaleY(1.02);
|
||||
}
|
||||
|
||||
.large-switch:hover {
|
||||
background: rgb(37, 35, 64);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: TTNormsPro-Bold;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
33
src/lib/components/player-controls.svelte
Normal file
33
src/lib/components/player-controls.svelte
Normal file
@ -0,0 +1,33 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="play" on:click={() => dispatch('click')}>
|
||||
<img src="/icons/play.svg" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.play {
|
||||
background: rgba(25, 23, 54, 0.5);
|
||||
outline: none;
|
||||
border: medium none;
|
||||
display: flex;
|
||||
-moz-box-pack: center;
|
||||
justify-content: center;
|
||||
-moz-box-align: center;
|
||||
align-items: center;
|
||||
width: clamp(40px, -2rem + 8vw, 4.75rem);
|
||||
height: clamp(40px, -2rem + 8vw, 4.75rem);
|
||||
border-radius: 100%;
|
||||
cursor: pointer;
|
||||
box-shadow: rgba(86, 84, 135, 0.49) 0px 0px 0px 1px;
|
||||
margin: 0px clamp(0.25rem, -2rem + 8vw, 1rem);
|
||||
backdrop-filter: blur(34px);
|
||||
transition: box-shadow 0.4s ease-in-out 0s, background 0.3s ease-in-out 0s;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
40
src/lib/components/song.svelte
Normal file
40
src/lib/components/song.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<div class="player-wrapper">
|
||||
<div class="image-wrapper">
|
||||
<img src="https://images.unsplash.com/photo-1610412458272-c4032377e721?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwyMjcyMjd8MHwxfHNlYXJjaHwxNDMwfHxhYnN0cmFjdHxlbnwxfHx8fDE2MjE2MDY0Nzc&ixlib=rb-1.2.1&q=80&w=1080" alt="">
|
||||
</div>
|
||||
<div class="song-info-wrapper">
|
||||
<h3 class="song-title">perfect moments</h3>
|
||||
<p class="song-info">ATMOSPHERIC • MEDIUM NEURAL EFFECT</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.player-wrapper {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.image-wrapper {
|
||||
margin-right: 1.5rem
|
||||
}
|
||||
|
||||
.image-wrapper img {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.song-title {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.song-info {
|
||||
font-size: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
letter-spacing: 0.2rem;
|
||||
font-weight: 700;
|
||||
font-family: TTNormsPro-Regular;
|
||||
}
|
||||
</style>
|
45
src/lib/components/switch.svelte
Normal file
45
src/lib/components/switch.svelte
Normal file
@ -0,0 +1,45 @@
|
||||
<script>
|
||||
export let toggled = false;
|
||||
</script>
|
||||
|
||||
<div class="switch" class:active={toggled}>
|
||||
<div class="notch" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.switch {
|
||||
cursor: pointer;
|
||||
border-radius: 22px;
|
||||
width: 22px;
|
||||
height: 13.75px;
|
||||
position: relative;
|
||||
transition: background 0.2s ease-in-out 0s, box-shadow 0.2s ease-in-out 0s,
|
||||
border 0.2s ease-in-out 0s;
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.switch.active {
|
||||
border: 0;
|
||||
background: linear-gradient(100.23deg, rgb(73, 21, 248) -26.81%, rgb(255, 73, 107) 84.28%);
|
||||
box-shadow: rgba(147, 35, 102, 0.4) 0px 2.54251px 11.4413px;
|
||||
}
|
||||
|
||||
.switch.active > .notch {
|
||||
left: calc(100% - 11.75px);
|
||||
}
|
||||
|
||||
.notch {
|
||||
cursor: pointer;
|
||||
background-color: rgb(255, 255, 255);
|
||||
width: 9.75px;
|
||||
height: 9.75px;
|
||||
border-radius: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 1px;
|
||||
transform: translateY(-50%);
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 2px 4px 6px;
|
||||
transition: all 0.3s ease 0s;
|
||||
}
|
||||
</style>
|
1
src/lib/modal.js
Normal file
1
src/lib/modal.js
Normal file
@ -0,0 +1 @@
|
||||
export const ssr = false;
|
90
src/lib/modal.svelte
Normal file
90
src/lib/modal.svelte
Normal file
@ -0,0 +1,90 @@
|
||||
<script context="module" lang="ts">
|
||||
let onTop: string //keeping track of which open modal is on top
|
||||
const modals = {} //all modals get registered here for easy future access
|
||||
|
||||
// returns an object for the modal specified by `id`, which contains the API functions (`open` and `close` )
|
||||
export function getModal(id = '') {
|
||||
return modals[id]
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { onDestroy } from 'svelte'
|
||||
|
||||
let topDiv
|
||||
let visible = false
|
||||
let prevOnTop
|
||||
let closeCallback: Function
|
||||
|
||||
export let id: string = ''
|
||||
export let title: string = id
|
||||
|
||||
function keyPress(ev: KeyboardEvent) {
|
||||
//only respond if the current modal is the top one
|
||||
if (ev.key == 'Escape' && onTop == topDiv) close() //ESC
|
||||
}
|
||||
|
||||
/** API **/
|
||||
function open(callback: Function) {
|
||||
closeCallback = callback
|
||||
if (visible) return
|
||||
prevOnTop = onTop
|
||||
onTop = topDiv
|
||||
|
||||
//this prevents scrolling of the main window on larger screens
|
||||
document.body.style.overflow = 'hidden'
|
||||
|
||||
visible = true
|
||||
//Move the modal in the DOM to be the last child of <BODY> so that it can be on top of everything
|
||||
document.body.appendChild(topDiv)
|
||||
}
|
||||
|
||||
function close(retVal: any) {
|
||||
if (!visible) return
|
||||
onTop = prevOnTop
|
||||
if (onTop == null) document.body.style.overflow = ''
|
||||
visible = false
|
||||
if (closeCallback) closeCallback(retVal)
|
||||
}
|
||||
|
||||
//expose the API
|
||||
modals[id] = { open, close }
|
||||
|
||||
onDestroy(() => {
|
||||
delete modals[id]
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={keyPress} />
|
||||
|
||||
<dialog id="topModal" class:visible bind:this={topDiv} on:click={() => close()}>
|
||||
<article id="modal" on:click|stopPropagation={() => {}}>
|
||||
<header>
|
||||
<a href="#" aria-label="Close" class="close" on:click={()=>close()} />
|
||||
{title}
|
||||
</header>
|
||||
<div id="modal-content">
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
#topModal {
|
||||
visibility: hidden;
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #4448;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.visible {
|
||||
visibility: visible !important;
|
||||
}
|
||||
</style>
|
102
src/lib/module/filter.svelte
Normal file
102
src/lib/module/filter.svelte
Normal file
@ -0,0 +1,102 @@
|
||||
<script lang="ts">
|
||||
import LargeButton from '$lib/components/large-button.svelte';
|
||||
import LargeSwitch from '$lib/components/large-switch.svelte';
|
||||
|
||||
let nodeRef: Node;
|
||||
</script>
|
||||
|
||||
<div class="filter-component" bind:this={nodeRef}>
|
||||
<div class="filter-wrapper">
|
||||
<div class="filter-close" on:click={() => nodeRef.parentNode?.removeChild(nodeRef)}>
|
||||
<img src="/icons/close.svg" alt="" />
|
||||
</div>
|
||||
<div class="filter-sections-wrapper">
|
||||
<div class="filter-section">
|
||||
<div class="filter-title-wrapper">
|
||||
<div class="filter-title">Activity</div>
|
||||
</div>
|
||||
<div class="filter-options-wrapper">
|
||||
<LargeButton
|
||||
title="deep sleep"
|
||||
description="Music designed to promote healthy and prolonged rest."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-section">
|
||||
<div class="filter-title-wrapper">
|
||||
<div class="filter-title">Genre</div>
|
||||
</div>
|
||||
<div class="filter-options-wrapper">
|
||||
<LargeSwitch title="Beach" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-section" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.filter-component {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
padding: 15vh 5vw;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
width: 100vw;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.filter-wrapper {
|
||||
border-radius: 20px;
|
||||
padding: 0px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
scrollbar-width: none;
|
||||
background: rgb(33, 29, 63);
|
||||
backdrop-filter: blur(64px);
|
||||
border: 1px solid rgba(55, 62, 91, 0.7);
|
||||
box-shadow: rgba(25, 23, 54, 0.65) 0px 20px 50px;
|
||||
}
|
||||
|
||||
.filter-sections-wrapper {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-section:nth-child(2) {
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
padding: 4rem;
|
||||
overflow: hidden auto;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.filter-title-wrapper {
|
||||
margin-bottom: 2.75rem;
|
||||
letter-spacing: 0.2rem;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.filter-title {
|
||||
font-family: TTNormsPro-Regular;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.filter-close {
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
right: 2rem;
|
||||
cursor: pointer;
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
20
src/lib/module/player.svelte
Normal file
20
src/lib/module/player.svelte
Normal file
@ -0,0 +1,20 @@
|
||||
<script>
|
||||
import Song from '$lib/components/song.svelte'
|
||||
|
||||
import PlayerControls from '$lib/components/player-controls.svelte'
|
||||
</script>
|
||||
|
||||
<div class="player">
|
||||
<Song />
|
||||
|
||||
<PlayerControls />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.player {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
}
|
||||
</style>
|
@ -1,18 +1,16 @@
|
||||
import lucia from "lucia-auth"
|
||||
import prismaAdapter from "@lucia-auth/adapter-prisma"
|
||||
import { dev } from "$app/environment"
|
||||
import { prisma } from "$lib/server/prisma"
|
||||
// @ts-ignore
|
||||
|
||||
import lucia from 'lucia-auth'
|
||||
import { sveltekit } from 'lucia-auth/middleware'
|
||||
import prisma from '@lucia-auth/adapter-prisma'
|
||||
import { prisma as prismaClient } from '$lib/server/prisma'
|
||||
import { dev } from '$app/environment'
|
||||
|
||||
export const auth = lucia({
|
||||
adapter: prismaAdapter(prisma),
|
||||
env: dev ? "DEV" : "PROD",
|
||||
transformUserData: (userData) => {
|
||||
return {
|
||||
userId: userData.id,
|
||||
username: userData.username,
|
||||
name: userData.name,
|
||||
}
|
||||
},
|
||||
// @ts-expect-error
|
||||
adapter: prisma(prismaClient),
|
||||
env: dev ? 'DEV' : 'PROD',
|
||||
middleware: sveltekit()
|
||||
})
|
||||
|
||||
export type Auth = typeof auth
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { LayoutServerLoad } from "./$types"
|
||||
|
||||
export const load: LayoutServerLoad = async ({ locals }) => {
|
||||
const { user, session } = await locals.validateUser()
|
||||
const { user, session } = await locals.auth.validateUser()
|
||||
|
||||
return { user }
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
<script lang="ts">
|
||||
import '@picocss/pico'
|
||||
import type { PageData } from './$types'
|
||||
export let data: PageData
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>
|
||||
<a href="/"> Blogly </a>
|
||||
</strong>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<form method="POST">
|
||||
<li><a href="/">Home</a></li>
|
||||
{#if !data.user}
|
||||
<li><a href="/register">Register</a></li>
|
||||
<li><a href="/login" role="button">Login</a></li>
|
||||
{:else}
|
||||
<li>
|
||||
<button formaction="/logout" type="submit" role="button">Logout</button>
|
||||
</li>
|
||||
{/if}
|
||||
</form>
|
||||
</ul>
|
||||
</nav>
|
||||
<slot />
|
||||
</div>
|
@ -10,7 +10,7 @@ export const load: PageServerLoad = async () => {
|
||||
|
||||
export const actions: Actions = {
|
||||
createArticle: async ({ request, locals }) => {
|
||||
const { user, session } = await locals.validateUser()
|
||||
const { user, session } = await locals.auth.validateUser()
|
||||
if (!(user && session)) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
@ -37,7 +37,7 @@ export const actions: Actions = {
|
||||
}
|
||||
},
|
||||
deleteArticle: async ({ url, locals }) => {
|
||||
const { user, session } = await locals.validateUser()
|
||||
const { user, session } = await locals.auth.validateUser()
|
||||
if (!(user && session)) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
export let data: PageData;
|
||||
|
||||
$: ({ articles } = data)
|
||||
</script>
|
||||
|
@ -1,71 +0,0 @@
|
||||
import type { Actions, PageServerLoad } from "./$types"
|
||||
import { prisma } from "$lib/server/prisma"
|
||||
import { error, fail } from "@sveltejs/kit"
|
||||
|
||||
export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
const { user, session } = await locals.validateUser()
|
||||
if (!(user && session)) {
|
||||
throw error(401, "Unauthorized")
|
||||
}
|
||||
|
||||
const getArticle = async (userId: string) => {
|
||||
const article = await prisma.article.findUnique({
|
||||
where: {
|
||||
id: Number(params.articleId),
|
||||
},
|
||||
})
|
||||
if (!article) {
|
||||
throw error(404, "Article not found")
|
||||
}
|
||||
if (article.userId !== user.userId) {
|
||||
throw error(403, "Unauthorized")
|
||||
}
|
||||
|
||||
return article
|
||||
}
|
||||
|
||||
return {
|
||||
article: getArticle(user.userId),
|
||||
}
|
||||
}
|
||||
|
||||
export const actions: Actions = {
|
||||
updateArticle: async ({ request, params, locals }) => {
|
||||
const { user, session } = await locals.validateUser()
|
||||
if (!(user && session)) {
|
||||
throw error(401, "Unauthorized")
|
||||
}
|
||||
|
||||
const { title, content } = Object.fromEntries(
|
||||
await request.formData(),
|
||||
) as Record<string, string>
|
||||
|
||||
try {
|
||||
const article = await prisma.article.findUniqueOrThrow({
|
||||
where: {
|
||||
id: Number(params.articleId),
|
||||
},
|
||||
})
|
||||
|
||||
if (article.userId !== user.userId) {
|
||||
throw error(403, "Forbidden to edit this article.")
|
||||
}
|
||||
await prisma.article.update({
|
||||
where: {
|
||||
id: Number(params.articleId),
|
||||
},
|
||||
data: {
|
||||
title,
|
||||
content,
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return fail(500, { message: "Could not update article" })
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
}
|
||||
},
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
$: ({ article } = data)
|
||||
</script>
|
||||
|
||||
<form action="?/updateArticle" method="POST">
|
||||
<h3>Editing: {article.title}</h3>
|
||||
<label for="title"> Title </label>
|
||||
<input type="text" id="title" name="title" value={article.title} />
|
||||
<label for="title"> Title </label>
|
||||
<textarea id="content" name="content" rows={5} value={article.content} />
|
||||
<button type="submit">Update Article</button>
|
||||
</form>
|
0
src/routes/[mental_state]/+layout.server.ts
Normal file
0
src/routes/[mental_state]/+layout.server.ts
Normal file
41
src/routes/[mental_state]/+layout.svelte
Normal file
41
src/routes/[mental_state]/+layout.svelte
Normal file
@ -0,0 +1,41 @@
|
||||
<header class="header">
|
||||
<div class="left-wrapper">
|
||||
<div class="logo-wrapper">
|
||||
<img src="/logo.svg" alt="" class="logo" />
|
||||
</div>
|
||||
|
||||
<div class="activity-selector-wrapper">
|
||||
<select name="activity" id="">
|
||||
<option value="deep_work">deep work</option>
|
||||
<option value="learning">learning</option>
|
||||
<option value="creativity">creativity</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<slot />
|
||||
|
||||
<style>
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.left-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
24
src/routes/[mental_state]/+page.svelte
Normal file
24
src/routes/[mental_state]/+page.svelte
Normal file
@ -0,0 +1,24 @@
|
||||
<script>
|
||||
import Player from '$lib/module/player.svelte'
|
||||
|
||||
import Filter from '$lib/module/filter.svelte';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Filter />
|
||||
|
||||
<div class="player-wrapper">
|
||||
<Player />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.player-wrapper {
|
||||
position: fixed;
|
||||
bottom: 0
|
||||
}
|
||||
</style>
|
7
src/routes/[mental_state]/stores.js
Normal file
7
src/routes/[mental_state]/stores.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
const isPlaying = writable(false);
|
||||
|
||||
const songPreferedActivity = writable("")
|
||||
const songPreferedGenres = writable([])
|
||||
const songPreferedNEL = writable("")
|
@ -3,7 +3,7 @@ import { fail, redirect } from "@sveltejs/kit"
|
||||
import type { Actions, PageServerLoad } from "./$types"
|
||||
|
||||
export const load: PageServerLoad = async ({ locals }) => {
|
||||
const session = await locals.validate()
|
||||
const session = await locals.auth.validate()
|
||||
if (session) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
@ -16,9 +16,9 @@ export const actions: Actions = {
|
||||
) as Record<string, string>
|
||||
|
||||
try {
|
||||
const key = await auth.validateKeyPassword("username", username, password)
|
||||
const key = await auth.useKey("username", username, password)
|
||||
const session = await auth.createSession(key.userId)
|
||||
locals.setSession(session)
|
||||
locals.auth.setSession(session)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return fail(400, { message: "Could not login user." })
|
||||
|
@ -3,7 +3,7 @@ import { redirect } from "@sveltejs/kit"
|
||||
import type { RequestHandler } from "./$types"
|
||||
|
||||
export const POST: RequestHandler = async ({ locals }) => {
|
||||
const session = await locals.validate()
|
||||
const session = await locals.auth.validate()
|
||||
if (!session) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { fail, redirect } from "@sveltejs/kit"
|
||||
import type { Actions, PageServerLoad } from "./$types"
|
||||
|
||||
export const load: PageServerLoad = async ({ locals }) => {
|
||||
const session = await locals.validate()
|
||||
const session = await locals.auth.validate()
|
||||
if (session) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
@ -17,7 +17,7 @@ export const actions: Actions = {
|
||||
|
||||
try {
|
||||
await auth.createUser({
|
||||
key: {
|
||||
primaryKey: {
|
||||
providerId: "username",
|
||||
providerUserId: username,
|
||||
password,
|
||||
|
BIN
static/fonts/TTNormsPro-Bold.ttf
Normal file
BIN
static/fonts/TTNormsPro-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/TTNormsPro-Medium.ttf
Normal file
BIN
static/fonts/TTNormsPro-Medium.ttf
Normal file
Binary file not shown.
BIN
static/fonts/TTNormsPro-Regular.ttf
Normal file
BIN
static/fonts/TTNormsPro-Regular.ttf
Normal file
Binary file not shown.
4
static/icons/close.svg
Normal file
4
static/icons/close.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 6L6 18" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 6L18 18" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 306 B |
10
static/icons/play.svg
Normal file
10
static/icons/play.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1_2)">
|
||||
<path d="M16.3441 8.31926L3.86508 0.137426C3.60968 -0.0294838 3.28107 -0.0458474 3.01152 0.0965164C2.74031 0.23888 2.57143 0.516244 2.57143 0.818154V17.1818C2.57143 17.4837 2.74031 17.7611 3.01069 17.9035C3.13381 17.9681 3.26859 18 3.40336 18C3.56476 18 3.72615 17.9534 3.86508 17.8625L16.3441 9.68071C16.5754 9.52853 16.7143 9.27326 16.7143 8.99999C16.7143 8.72671 16.5754 8.47144 16.3441 8.31926Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1_2">
|
||||
<rect width="18" height="18" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 651 B |
1
static/logo.svg
Normal file
1
static/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="2115" width="2500" xmlns="http://www.w3.org/2000/svg" viewBox="0.01 -0.004 140.12 118.62019900826458"><path d="M70.014 23.941a47.318 47.318 0 1 0 47.533 47.317 47.481 47.481 0 0 0-47.533-47.317zm18.733 33.571a6.792 6.792 0 1 1-6.822 6.791 6.8 6.8 0 0 1 6.822-6.792zm-36.069 0a6.792 6.792 0 1 1-6.822 6.791 6.8 6.8 0 0 1 6.822-6.792zm44.453 24.455c-.56 3.288-4.185 22.167-26.32 22.167-21.595 0-26.75-20.546-26.75-22.167 0 0-1.127-4.324 4.054-3.451 6.309 1.063 15.754 1.345 21.865 1.345 7.317 0 17.679-.538 22.2-1 4.992-.503 5.197 1.669 4.951 3.106zm34.62-38.328h-1.345C126.288 32.727 110.646-.004 71.131-.004c-44.712 0-58.535 35.513-61.106 43.643H8.388C.366 43.639.01 52.517.01 52.517v21.471c0 12.422 12.3 9.758 16.578 9.758s4.456-5.5 4.456-5.5V46.658a4.814 4.814 0 0 0-3.989-2.9c3.3-9.462 16.137-37.042 54.073-37.042 32.339 0 46.676 24.03 52.062 37.022a4.862 4.862 0 0 0-4.094 2.92V78.25s.178 5.5 4.456 5.5 16.578 2.664 16.578-9.758V52.517s-.355-8.878-8.378-8.878z" fill="#fff" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 1018 B |
Loading…
Reference in New Issue
Block a user