Init backend, frontend and DB schema

This commit is contained in:
2024-08-03 10:44:42 +02:00
parent ddd7f7221b
commit 777038e0b4
23 changed files with 1917 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Repozytorium muzyczne</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module" src="src/index.tsx"></script>
</head>
<body></body>
</html>

View File

@@ -0,0 +1,18 @@
{
"name": "frontend",
"license": "UNLICENSED",
"private": true,
"type": "module",
"devDependencies": {
"@vanilla-extract/css": "catalog:",
"@vanilla-extract/vite-plugin": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
},
"dependencies": {
"@effect/schema": "catalog:",
"effect": "catalog:",
"fast-check": "catalog:",
"preact": "catalog:"
}
}

View File

@@ -0,0 +1,20 @@
import { globalStyle } from "@vanilla-extract/css";
globalStyle("html, body", {
margin: 0,
padding: 0,
backgroundColor: "white",
color: "black",
fontFamily: "system-ui, sans-serif",
fontSize: 16,
fontWeight: "normal",
"@media": {
"(prefers-color-scheme: dark)": {
backgroundColor: "black",
color: "white",
},
},
});

View File

@@ -0,0 +1,5 @@
import { render } from "preact";
import "./index.css";
render(<p>Hello World</p>, document.body);

View File

@@ -0,0 +1,63 @@
import { identity } from "effect";
import { useLayoutEffect, useState } from "preact/hooks";
export type Update<T> = T | ((prev: T) => T);
export type Updater<T> = (action: Update<T>) => void;
export interface Store {
readonly count: number;
}
let store: Store = Object.freeze<Store>({
count: 0,
});
// --- STORE IMPLEMENTATION ----------------------------------------------------
class Listener<T> {
private lastState: T;
constructor(
readonly selector: Selector<T>,
readonly setState: (state: T) => void,
) {
this.lastState = selector(store);
}
react() {
const state = this.selector(store);
if (!Object.is(this.lastState, state)) {
this.lastState = state;
this.setState(state);
}
}
}
const listeners = new Set<Listener<any>>();
export type Selector<T> = (store: Store) => T;
function set(action: Partial<Store> | ((store: Store) => Partial<Store>), replace?: false): void;
function set(action: Update<Store>, replace: true): void;
function set(action: Partial<Store> | ((store: Store) => Partial<Store>), replace: boolean = false): void {
const nextPartial = typeof action === "function" ? action(store) : action;
if (Object.is(store, nextPartial)) return;
store = Object.freeze(replace ? nextPartial as Store : Object.assign({}, store, nextPartial));
for (const listener of listeners) {
listener.react();
}
}
export function useStore<T = Store>(selector: Selector<T> = identity as Selector<T>): T {
const [state, setState] = useState(() => selector(store));
useLayoutEffect(() => {
const listener = new Listener(selector, setState);
listeners.add(listener);
return () => listeners.delete(listener);
}, []);
return state;
}

View File

@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.base.json",
}

View File

@@ -0,0 +1,6 @@
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
/** @type {import("vite").UserConfig} */
export default {
plugins: [vanillaExtractPlugin()],
};