diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..6a35774 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,26 @@ +name: Docker +on: + push: + branches: + - dev + - main + # Run tests for any PRs. + pull_request: + branches: + - dev + - main +env: + IMAGE_NAME: marks +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Run tests + run: | + if [ -f docker-compose.test.yml ]; then + docker-compose --file docker-compose.test.yml build + docker-compose --file docker-compose.test.yml run sut + else + docker build . --file Dockerfile + fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..36ce525 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,47 @@ +name: Lint +on: + push: + branches: + - dev + - main + pull_request: + branches: + - dev + - main +jobs: + backend-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + - uses: actions/setup-node@v7 + with: + node-version: 24 + cache: npm + cache-dependency-path: web/package-lock.json + - name: Build frontend + run: | + cd web + npm ci + npm run build + - name: golangci-lint + uses: golangci/golangci-lint-action@v9 + with: + version: v2.12.2 + + frontend-lint: + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: 24 + cache: npm + cache-dependency-path: web/package-lock.json + - run: npm ci + - run: npm run lint diff --git a/docs.org b/docs.org new file mode 100644 index 0000000..86134ee --- /dev/null +++ b/docs.org @@ -0,0 +1,24 @@ +* Database Schema + +** Events +- id (UUID) (PRIMARY) +- name (TEXT) (NOT NULL) +- created_at (TIMESTAMP) (NOT NULL) +- created_by (UUID) (NOT NULL) +- status (TEXT) (NOT NULL) (open|archived) + +** Timers +- user_uuid (UUID) (NOT NULL) UNIQUE(user_uuid,event_id) # uniquely identifies a user's timer for an event +- event_id (UUID) (NOT NULL) FOREIGN KEY(event_id) REFERENCES events(id) # references to events(id) +- start_time (TIMESTAMP) +- end_time (TIMESTAMP) + + +** Audit Logs +- id (UUID) (PRIMARY KEY) +- event_id (UUID) (NOT NULL) +- user_uuid (UUID) (NOT NULL) +- action (TEXT) (NOT NULL) +- created_at (TIMESTAMP) (NOT NULL) + +* API #TODO diff --git a/tmp/build-errors.log b/tmp/build-errors.log index ccd0cd6..b27e525 100644 --- a/tmp/build-errors.log +++ b/tmp/build-errors.log @@ -1 +1 @@ -exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/tmp/main b/tmp/main new file mode 100755 index 0000000..bb786e5 Binary files /dev/null and b/tmp/main differ diff --git a/web/.prettierrc b/web/.prettierrc new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/web/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/web/README.md b/web/README.md index c300135..db579d2 100644 --- a/web/README.md +++ b/web/README.md @@ -17,9 +17,9 @@ If you are developing a production application, we recommend updating the config ```js export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(["dist"]), { - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], extends: [ // Other configs... @@ -34,42 +34,40 @@ export default defineConfig([ ], languageOptions: { parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], + project: ["./tsconfig.node.json", "./tsconfig.app.json"], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, -]) - +]); ``` You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: ```js // eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' +import reactX from "eslint-plugin-react-x"; +import reactDom from "eslint-plugin-react-dom"; export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(["dist"]), { - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], extends: [ // Other configs... // Enable lint rules for React - reactX.configs['recommended-typescript'], + reactX.configs["recommended-typescript"], // Enable lint rules for React DOM reactDom.configs.recommended, ], languageOptions: { parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], + project: ["./tsconfig.node.json", "./tsconfig.app.json"], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, -]) - +]); ``` diff --git a/web/eslint.config.js b/web/eslint.config.js index ef614d2..da6f026 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js @@ -1,14 +1,14 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { defineConfig, globalIgnores } from 'eslint/config' +import js from "@eslint/js"; +import globals from "globals"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; +import tseslint from "typescript-eslint"; +import { defineConfig, globalIgnores } from "eslint/config"; export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(["dist"]), { - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], extends: [ js.configs.recommended, tseslint.configs.recommended, @@ -19,4 +19,4 @@ export default defineConfig([ globals: globals.browser, }, }, -]) +]); diff --git a/web/package-lock.json b/web/package-lock.json index 7280b88..b1b23b1 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -21,6 +21,7 @@ "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.3", "globals": "^17.7.0", + "prettier": "^3.9.6", "typescript": "~6.0.2", "typescript-eslint": "^8.65.0", "vite": "^8.2.0" @@ -2286,6 +2287,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/web/package.json b/web/package.json index 662a21e..98e80cd 100644 --- a/web/package.json +++ b/web/package.json @@ -23,6 +23,7 @@ "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.3", "globals": "^17.7.0", + "prettier": "^3.9.6", "typescript": "~6.0.2", "typescript-eslint": "^8.65.0", "vite": "^8.2.0" diff --git a/web/src/App.css b/web/src/App.css index f90339d..f460279 100644 --- a/web/src/App.css +++ b/web/src/App.css @@ -167,7 +167,7 @@ &::before, &::after { - content: ''; + content: ""; position: absolute; top: -4.5px; border: 5px solid transparent; diff --git a/web/src/App.tsx b/web/src/App.tsx index a66b5ef..1fd432d 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,11 +1,11 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from './assets/vite.svg' -import heroImg from './assets/hero.png' -import './App.css' +import { useState } from "react"; +import reactLogo from "./assets/react.svg"; +import viteLogo from "./assets/vite.svg"; +import heroImg from "./assets/hero.png"; +import "./App.css"; function App() { - const [count, setCount] = useState(0) + const [count, setCount] = useState(0); return ( <> @@ -116,7 +116,7 @@ function App() {
- ) + ); } -export default App +export default App; diff --git a/web/src/index.css b/web/src/index.css index 5fb3313..aad5cb1 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -11,8 +11,8 @@ --shadow: rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px; - --sans: system-ui, 'Segoe UI', Roboto, sans-serif; - --heading: system-ui, 'Segoe UI', Roboto, sans-serif; + --sans: system-ui, "Segoe UI", Roboto, sans-serif; + --heading: system-ui, "Segoe UI", Roboto, sans-serif; --mono: ui-monospace, Consolas, monospace; font: 18px/145% var(--sans); diff --git a/web/src/main.tsx b/web/src/main.tsx index bef5202..eff7ccc 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -1,10 +1,10 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; -createRoot(document.getElementById('root')!).render( +createRoot(document.getElementById("root")!).render( , -) +); diff --git a/web/vite.config.ts b/web/vite.config.ts index 8b0f57b..0e43ae8 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; // https://vite.dev/config/ export default defineConfig({ plugins: [react()], -}) +});