diff --git a/vue-frontend/.env b/vue-frontend/.env new file mode 100644 index 0000000..dd97135 --- /dev/null +++ b/vue-frontend/.env @@ -0,0 +1 @@ +BASE_URL=https//5173.tzgyn.com diff --git a/vue-frontend/.gitignore b/vue-frontend/.gitignore new file mode 100644 index 0000000..38adffa --- /dev/null +++ b/vue-frontend/.gitignore @@ -0,0 +1,28 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/vue-frontend/.prettierrc.yaml b/vue-frontend/.prettierrc.yaml new file mode 100644 index 0000000..1439e2e --- /dev/null +++ b/vue-frontend/.prettierrc.yaml @@ -0,0 +1,16 @@ +--- +printWidth: 80 +tabWidth: 4 +useTabs: true +semi: false +singleQuote: true +quoteProps: consistent +jsxSingleQuote: true +trailingComma: es5 +bracketSpacing: true +bracketSameLine: true +arrowParens: always +htmlWhitespaceSensitivity: strict +vueIndentScriptAndStyle: false +singleAttributePerLine: true +plugins: [prettier-plugin-tailwindcss] diff --git a/vue-frontend/.vscode/extensions.json b/vue-frontend/.vscode/extensions.json new file mode 100644 index 0000000..c0a6e5a --- /dev/null +++ b/vue-frontend/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] +} diff --git a/vue-frontend/README.md b/vue-frontend/README.md new file mode 100644 index 0000000..e1cff9b --- /dev/null +++ b/vue-frontend/README.md @@ -0,0 +1,40 @@ +# vue-frontend + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` diff --git a/vue-frontend/bun.lockb b/vue-frontend/bun.lockb new file mode 100755 index 0000000..f18d3ea Binary files /dev/null and b/vue-frontend/bun.lockb differ diff --git a/vue-frontend/components.json b/vue-frontend/components.json new file mode 100644 index 0000000..59524eb --- /dev/null +++ b/vue-frontend/components.json @@ -0,0 +1,15 @@ +{ + "style": "default", + "typescript": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/assets/index.css", + "baseColor": "slate", + "cssVariables": true + }, + "framework": "vite", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/vue-frontend/env.d.ts b/vue-frontend/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/vue-frontend/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/vue-frontend/index.html b/vue-frontend/index.html new file mode 100644 index 0000000..a888544 --- /dev/null +++ b/vue-frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/vue-frontend/package.json b/vue-frontend/package.json new file mode 100644 index 0000000..183d8e2 --- /dev/null +++ b/vue-frontend/package.json @@ -0,0 +1,38 @@ +{ + "name": "vue-frontend", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false" + }, + "dependencies": { + "@vueuse/core": "^10.5.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", + "lucide-vue-next": "^0.288.0", + "radix-vue": "^0.4.1", + "tailwind-merge": "^1.14.0", + "tailwindcss-animate": "^1.0.7", + "vue": "^3.3.4", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node18": "^18.2.2", + "@types/node": "^18.18.5", + "@vitejs/plugin-vue": "^4.4.0", + "@vue/tsconfig": "^0.4.0", + "autoprefixer": "^10.4.16", + "npm-run-all2": "^6.1.1", + "postcss": "^8.4.31", + "prettier": "^3.0.3", + "prettier-plugin-tailwindcss": "^0.5.6", + "tailwindcss": "^3.3.3", + "typescript": "~5.2.0", + "vite": "^4.4.11", + "vue-tsc": "^1.8.19" + } +} diff --git a/vue-frontend/postcss.config.js b/vue-frontend/postcss.config.js new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/vue-frontend/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/vue-frontend/public/favicon.ico b/vue-frontend/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/vue-frontend/public/favicon.ico differ diff --git a/vue-frontend/src/App.vue b/vue-frontend/src/App.vue new file mode 100644 index 0000000..e9f44f1 --- /dev/null +++ b/vue-frontend/src/App.vue @@ -0,0 +1,11 @@ + + + diff --git a/vue-frontend/src/assets/index.css b/vue-frontend/src/assets/index.css new file mode 100644 index 0000000..865834e --- /dev/null +++ b/vue-frontend/src/assets/index.css @@ -0,0 +1,80 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 10% 3.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} + +#app { + @apply h-screen w-screen; +} diff --git a/vue-frontend/src/assets/logo.svg b/vue-frontend/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/vue-frontend/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/vue-frontend/src/components/Navbar.vue b/vue-frontend/src/components/Navbar.vue new file mode 100644 index 0000000..1b27eb8 --- /dev/null +++ b/vue-frontend/src/components/Navbar.vue @@ -0,0 +1,14 @@ + + diff --git a/vue-frontend/src/components/ToggleThemeButton.vue b/vue-frontend/src/components/ToggleThemeButton.vue new file mode 100644 index 0000000..c2054a8 --- /dev/null +++ b/vue-frontend/src/components/ToggleThemeButton.vue @@ -0,0 +1,21 @@ + + + diff --git a/vue-frontend/src/components/UserLoginForm.vue b/vue-frontend/src/components/UserLoginForm.vue new file mode 100644 index 0000000..e93a791 --- /dev/null +++ b/vue-frontend/src/components/UserLoginForm.vue @@ -0,0 +1,76 @@ + + + diff --git a/vue-frontend/src/components/UserSignUpForm.vue b/vue-frontend/src/components/UserSignUpForm.vue new file mode 100644 index 0000000..bde2cd6 --- /dev/null +++ b/vue-frontend/src/components/UserSignUpForm.vue @@ -0,0 +1,84 @@ + + + diff --git a/vue-frontend/src/components/ui/button/Button.vue b/vue-frontend/src/components/ui/button/Button.vue new file mode 100644 index 0000000..d721b1a --- /dev/null +++ b/vue-frontend/src/components/ui/button/Button.vue @@ -0,0 +1,23 @@ + + + diff --git a/vue-frontend/src/components/ui/button/index.ts b/vue-frontend/src/components/ui/button/index.ts new file mode 100644 index 0000000..4211057 --- /dev/null +++ b/vue-frontend/src/components/ui/button/index.ts @@ -0,0 +1,33 @@ +import { cva } from 'class-variance-authority' + +export { default as Button } from './Button.vue' + +export const buttonVariants = cva( + 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', + { + variants: { + variant: { + default: + 'bg-primary-foreground text-primary hover:bg-primary-foreground/90', + destructive: + 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: + 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + secondary: + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-10 px-4 py-2', + sm: 'h-9 rounded-md px-3', + lg: 'h-11 rounded-md px-8', + icon: 'h-10 w-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } +) diff --git a/vue-frontend/src/components/ui/input/Input.vue b/vue-frontend/src/components/ui/input/Input.vue new file mode 100644 index 0000000..66ece7a --- /dev/null +++ b/vue-frontend/src/components/ui/input/Input.vue @@ -0,0 +1,22 @@ + + + diff --git a/vue-frontend/src/components/ui/input/index.ts b/vue-frontend/src/components/ui/input/index.ts new file mode 100644 index 0000000..a691dd6 --- /dev/null +++ b/vue-frontend/src/components/ui/input/index.ts @@ -0,0 +1 @@ +export { default as Input } from './Input.vue' diff --git a/vue-frontend/src/components/ui/label/Label.vue b/vue-frontend/src/components/ui/label/Label.vue new file mode 100644 index 0000000..e44d139 --- /dev/null +++ b/vue-frontend/src/components/ui/label/Label.vue @@ -0,0 +1,20 @@ + + + diff --git a/vue-frontend/src/components/ui/label/index.ts b/vue-frontend/src/components/ui/label/index.ts new file mode 100644 index 0000000..572c2f0 --- /dev/null +++ b/vue-frontend/src/components/ui/label/index.ts @@ -0,0 +1 @@ +export { default as Label } from './Label.vue' diff --git a/vue-frontend/src/lib/auth.ts b/vue-frontend/src/lib/auth.ts new file mode 100644 index 0000000..b6c2799 --- /dev/null +++ b/vue-frontend/src/lib/auth.ts @@ -0,0 +1,3 @@ +export const isAuthenticated = async () => { + return false +} diff --git a/vue-frontend/src/lib/utils.ts b/vue-frontend/src/lib/utils.ts new file mode 100644 index 0000000..24470b3 --- /dev/null +++ b/vue-frontend/src/lib/utils.ts @@ -0,0 +1,7 @@ +import { type ClassValue, clsx } from 'clsx' +import { twMerge } from 'tailwind-merge' +import { camelize, getCurrentInstance, toHandlerKey } from 'vue' + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/vue-frontend/src/main.ts b/vue-frontend/src/main.ts new file mode 100644 index 0000000..72d93d8 --- /dev/null +++ b/vue-frontend/src/main.ts @@ -0,0 +1,11 @@ +import "./assets/index.css"; + +import { createApp } from "vue"; +import App from "./App.vue"; +import router from "./router"; + +const app = createApp(App); + +app.use(router); + +app.mount("#app"); diff --git a/vue-frontend/src/router/index.ts b/vue-frontend/src/router/index.ts new file mode 100644 index 0000000..a5794bf --- /dev/null +++ b/vue-frontend/src/router/index.ts @@ -0,0 +1,37 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { isAuthenticated } from '@/lib/auth' +import HomeView from '@/views/HomeView.vue' +import LoginPage from '@/views/LoginPage.vue' +import SignUpPage from '@/views/SignUpPage.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + component: HomeView, + }, + { + path: '/login', + name: 'login', + component: LoginPage, + }, + { + path: '/signup', + name: 'signup', + component: SignUpPage, + }, + ], +}) + +router.beforeEach(async (to) => { + const isLoggedIn = await isAuthenticated() + if (isLoggedIn && (to.name === 'login' || to.name === 'signup')) { + return { name: 'home' } + } + if (!isLoggedIn && to.name !== 'login' && to.name !== 'signup') { + return { name: 'login' } + } +}) + +export default router diff --git a/vue-frontend/src/views/HomeView.vue b/vue-frontend/src/views/HomeView.vue new file mode 100644 index 0000000..0a45c22 --- /dev/null +++ b/vue-frontend/src/views/HomeView.vue @@ -0,0 +1,3 @@ + diff --git a/vue-frontend/src/views/LoginPage.vue b/vue-frontend/src/views/LoginPage.vue new file mode 100644 index 0000000..cd18c1e --- /dev/null +++ b/vue-frontend/src/views/LoginPage.vue @@ -0,0 +1,43 @@ + + + diff --git a/vue-frontend/src/views/SignUpPage.vue b/vue-frontend/src/views/SignUpPage.vue new file mode 100644 index 0000000..f759724 --- /dev/null +++ b/vue-frontend/src/views/SignUpPage.vue @@ -0,0 +1,43 @@ + + + diff --git a/vue-frontend/tailwind.config.js b/vue-frontend/tailwind.config.js new file mode 100644 index 0000000..aedb250 --- /dev/null +++ b/vue-frontend/tailwind.config.js @@ -0,0 +1,79 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ['class'], + + content: [ + './pages/**/*.{ts,tsx,vue}', + './components/**/*.{ts,tsx,vue}', + './app/**/*.{ts,tsx,vue}', + './src/**/*.{ts,tsx,vue}', + './index.html', + ], + + theme: { + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px', + }, + }, + extend: { + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', + }, + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + }, + keyframes: { + 'accordion-down': { + from: { height: 0 }, + to: { height: 'var(--radix-accordion-content-height)' }, + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: 0 }, + }, + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', + }, + }, + }, + plugins: [require('tailwindcss-animate')], +} diff --git a/vue-frontend/tsconfig.app.json b/vue-frontend/tsconfig.app.json new file mode 100644 index 0000000..3e5b621 --- /dev/null +++ b/vue-frontend/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/vue-frontend/tsconfig.json b/vue-frontend/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/vue-frontend/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/vue-frontend/tsconfig.node.json b/vue-frontend/tsconfig.node.json new file mode 100644 index 0000000..dee96be --- /dev/null +++ b/vue-frontend/tsconfig.node.json @@ -0,0 +1,16 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/vue-frontend/vite.config.ts b/vue-frontend/vite.config.ts new file mode 100644 index 0000000..5c45e1d --- /dev/null +++ b/vue-frontend/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +})