From e2daa36a11385505d070de69553c414e4a275b07 Mon Sep 17 00:00:00 2001 From: Camilo Vega <59750365+camilovegag@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:58:01 -0500 Subject: [PATCH 1/9] 655 support markdown at develop (#656) * Replicate pr to support markdown at develop * update pnpm action to v4 --------- Co-authored-by: Diego Alzate --- .github/workflows/check-formatting.yml | 2 +- .github/workflows/lint.yml | 2 +- .../src/components/option-card/OptionCard.tsx | 13 ++++++++++++- .../tables/results-table/ResultsTable.tsx | 13 ++++++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-formatting.yml b/.github/workflows/check-formatting.yml index d4c8c816..09814185 100644 --- a/.github/workflows/check-formatting.yml +++ b/.github/workflows/check-formatting.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8 - name: Setup Node.js environment diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cab3377c..30740e9f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8 - name: Setup Node.js environment diff --git a/packages/berlin/src/components/option-card/OptionCard.tsx b/packages/berlin/src/components/option-card/OptionCard.tsx index 1072de63..53d10b7f 100644 --- a/packages/berlin/src/components/option-card/OptionCard.tsx +++ b/packages/berlin/src/components/option-card/OptionCard.tsx @@ -21,6 +21,8 @@ import { useNavigate, useParams } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import IconButton from '../icon-button'; +import Markdown from 'react-markdown'; +import Link from '../link'; type OptionCardProps = { option: GetCycleResponse['forumQuestions'][number]['questionOptions'][number]; @@ -161,7 +163,16 @@ function OptionCard({ Funding request: {option.fundingRequest} )} - {option.optionSubTitle && {option.optionSubTitle}} + {option.optionSubTitle && ( + {props.children}, + p: ({ node, ...props }) => {props.children}, + }} + > + {option.optionSubTitle} + + )} - {option.optionSubTitle} + {option.optionSubTitle && ( + {props.children}, + p: ({ node, ...props }) => {props.children}, + }} + > + {option.optionSubTitle} + + )} Research Output: {researchOutputValue} From 663a919e38711808d7989b3c2074ece7ecd3a2ca Mon Sep 17 00:00:00 2001 From: Camilo Vega <59750365+camilovegag@users.noreply.github.com> Date: Mon, 8 Jul 2024 07:57:01 -0500 Subject: [PATCH 2/9] 644 bring shadcn to develop (#645) * Install tailwind and lucide * Fix path errors * Remove tw deps and core scripts * Make dependencies dev dependencies * Run pnpm i --- package.json | 8 +- packages/berlin/components.json | 17 + packages/berlin/package.json | 29 + packages/berlin/postcss.config.js | 6 + packages/berlin/src/index.css | 76 +++ packages/berlin/src/lib/utils.ts | 6 + packages/berlin/src/main.tsx | 2 +- packages/berlin/tailwind.config.js | 77 +++ packages/berlin/tsconfig.json | 34 ++ packages/berlin/tsconfig.node.json | 11 + packages/berlin/vite.config.ts | 6 + pnpm-lock.yaml | 853 ++++++++++++++++++++++++++++- vite.config.ts | 18 - 13 files changed, 1104 insertions(+), 39 deletions(-) create mode 100644 packages/berlin/components.json create mode 100644 packages/berlin/postcss.config.js create mode 100644 packages/berlin/src/index.css create mode 100644 packages/berlin/src/lib/utils.ts create mode 100644 packages/berlin/tailwind.config.js create mode 100644 packages/berlin/tsconfig.json create mode 100644 packages/berlin/tsconfig.node.json delete mode 100644 vite.config.ts diff --git a/package.json b/package.json index 9debc022..fede6c6a 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,6 @@ "version": "1.0.0", "type": "module", "scripts": { - "core:dev": "pnpm -r --filter core dev", - "core:build": "pnpm -r --filter core build", - "core:preview": "pnpm -r --filter core preview", "berlin:dev": "pnpm -r --filter berlin dev", "berlin:build": "pnpm -r --filter berlin build", "berlin:preview": "pnpm -r --filter berlin preview", @@ -27,8 +24,12 @@ "@pcd/semaphore-identity-pcd": "^0.8.0", "@pcd/semaphore-signature-pcd": "^0.9.0", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-icons": "^1.3.0", "@tanstack/react-query": "^5.13.4", "@tanstack/react-query-devtools": "^5.13.5", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "lucide-react": "^0.397.0", "react": "^18.2.0", "react-content-loader": "^7.0.0", "react-dom": "^18.2.0", @@ -43,6 +44,7 @@ "devDependencies": { "@hookform/devtools": "^4.3.1", "@tanstack/eslint-plugin-query": "^5.18.0", + "@types/node": "^20.12.4", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@typescript-eslint/eslint-plugin": "^6.19.0", diff --git a/packages/berlin/components.json b/packages/berlin/components.json new file mode 100644 index 00000000..8a529f4e --- /dev/null +++ b/packages/berlin/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/_components", + "utils": "@/lib/utils" + } +} diff --git a/packages/berlin/package.json b/packages/berlin/package.json index 99cdc60f..98f43ed6 100644 --- a/packages/berlin/package.json +++ b/packages/berlin/package.json @@ -11,7 +11,36 @@ "preview": "vite preview" }, "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-navigation-menu": "^1.2.0", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-separator": "^1.1.0", + "@radix-ui/react-slot": "^1.0.2", "api": "workspace:*", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "cmdk": "^1.0.0", + "lucide-react": "^0.397.0", + "tailwind-merge": "^2.2.2", + "tailwindcss-animate": "^1.0.7", "ui": "workspace:*" + }, + "devDependencies": { + "@types/node": "^20.12.4", + "@types/react-dom": "^18.2.22", + "@types/react": "^18.3.3", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/parser": "^7.2.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.19", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.6", + "eslint": "^8.57.0", + "postcss-cli": "^11.0.0", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.3", + "vite-plugin-dts": "^3.8.1", + "vite": "^5.2.0" } } diff --git a/packages/berlin/postcss.config.js b/packages/berlin/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/packages/berlin/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/berlin/src/index.css b/packages/berlin/src/index.css new file mode 100644 index 00000000..8abdb15c --- /dev/null +++ b/packages/berlin/src/index.css @@ -0,0 +1,76 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/packages/berlin/src/lib/utils.ts b/packages/berlin/src/lib/utils.ts new file mode 100644 index 00000000..9ad0df42 --- /dev/null +++ b/packages/berlin/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/berlin/src/main.tsx b/packages/berlin/src/main.tsx index 95dc2ece..6f5ba456 100644 --- a/packages/berlin/src/main.tsx +++ b/packages/berlin/src/main.tsx @@ -6,7 +6,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import BerlinApp from './App.tsx'; import ThemedApp from './global.styled'; -// import 'ui/dist/style.css'; +import './index.css'; const queryClient = new QueryClient(); diff --git a/packages/berlin/tailwind.config.js b/packages/berlin/tailwind.config.js new file mode 100644 index 00000000..fe12db56 --- /dev/null +++ b/packages/berlin/tailwind.config.js @@ -0,0 +1,77 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ['class'], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: '', + 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/packages/berlin/tsconfig.json b/packages/berlin/tsconfig.json new file mode 100644 index 00000000..4605800c --- /dev/null +++ b/packages/berlin/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + /* Build */ + "outDir": "dist", + "declaration": true, + "declarationMap": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/packages/berlin/tsconfig.node.json b/packages/berlin/tsconfig.node.json new file mode 100644 index 00000000..97ede7ee --- /dev/null +++ b/packages/berlin/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/berlin/vite.config.ts b/packages/berlin/vite.config.ts index 5724869f..f7f51a87 100644 --- a/packages/berlin/vite.config.ts +++ b/packages/berlin/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { nodePolyfills } from 'vite-plugin-node-polyfills'; +import path from 'path'; // https://vitejs.dev/config/ export default defineConfig({ @@ -15,4 +16,9 @@ export default defineConfig({ }, }), ], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 342af50f..de659e56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,12 +26,24 @@ importers: '@radix-ui/react-dialog': specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-icons': + specifier: ^1.3.0 + version: 1.3.0(react@18.2.0) '@tanstack/react-query': specifier: ^5.13.4 version: 5.13.4(react@18.2.0) '@tanstack/react-query-devtools': specifier: ^5.13.5 version: 5.13.5(@tanstack/react-query@5.13.4(react@18.2.0))(react@18.2.0) + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + clsx: + specifier: ^2.1.0 + version: 2.1.0 + lucide-react: + specifier: ^0.397.0 + version: 0.397.0(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -69,6 +81,9 @@ importers: '@tanstack/eslint-plugin-query': specifier: ^5.18.0 version: 5.18.1(eslint@8.56.0)(typescript@5.5.2) + '@types/node': + specifier: ^20.12.4 + version: 20.12.4 '@types/react': specifier: ^18.2.37 version: 18.2.42 @@ -113,12 +128,94 @@ importers: packages/berlin: dependencies: + '@radix-ui/react-dialog': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-icons': + specifier: ^1.3.0 + version: 1.3.0(react@18.2.0) + '@radix-ui/react-navigation-menu': + specifier: ^1.2.0 + version: 1.2.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-popover': + specifier: ^1.0.7 + version: 1.0.7(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-separator': + specifier: ^1.1.0 + version: 1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': + specifier: ^1.0.2 + version: 1.0.2(@types/react@18.3.3)(react@18.2.0) api: specifier: workspace:* version: link:../api + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + clsx: + specifier: ^2.1.0 + version: 2.1.0 + cmdk: + specifier: ^1.0.0 + version: 1.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + lucide-react: + specifier: ^0.397.0 + version: 0.397.0(react@18.2.0) + tailwind-merge: + specifier: ^2.2.2 + version: 2.2.2 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.3) ui: specifier: workspace:* version: link:../ui + devDependencies: + '@types/node': + specifier: ^20.12.4 + version: 20.12.4 + '@types/react': + specifier: ^18.3.3 + version: 18.3.3 + '@types/react-dom': + specifier: ^18.2.22 + version: 18.2.24 + '@typescript-eslint/eslint-plugin': + specifier: ^7.2.0 + version: 7.5.0(@typescript-eslint/parser@7.5.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/parser': + specifier: ^7.2.0 + version: 7.5.0(eslint@8.57.0)(typescript@5.5.2) + '@vitejs/plugin-react': + specifier: ^4.2.1 + version: 4.2.1(vite@5.2.8(@types/node@20.12.4)) + autoprefixer: + specifier: ^10.4.19 + version: 10.4.19(postcss@8.4.38) + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-plugin-react-hooks: + specifier: ^4.6.0 + version: 4.6.0(eslint@8.57.0) + eslint-plugin-react-refresh: + specifier: ^0.4.6 + version: 0.4.6(eslint@8.57.0) + postcss: + specifier: ^8.4.38 + version: 8.4.38 + postcss-cli: + specifier: ^11.0.0 + version: 11.0.0(jiti@1.21.0)(postcss@8.4.38) + tailwindcss: + specifier: ^3.4.3 + version: 3.4.3 + vite: + specifier: ^5.2.0 + version: 5.2.8(@types/node@20.12.4) + vite-plugin-dts: + specifier: ^3.8.1 + version: 3.8.1(@types/node@20.12.4)(rollup@4.14.0)(typescript@5.5.2)(vite@5.2.8(@types/node@20.12.4)) packages/ui: dependencies: @@ -948,6 +1045,9 @@ packages: '@radix-ui/primitive@1.0.1': resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + '@radix-ui/primitive@1.1.0': + resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} + '@radix-ui/react-arrow@1.0.3': resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} peerDependencies: @@ -961,6 +1061,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.0': + resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-compose-refs@1.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -970,6 +1083,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-compose-refs@1.1.0': + resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-context@1.0.1': resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} peerDependencies: @@ -979,6 +1101,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-context@1.1.0': + resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dialog@1.0.5': resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} peerDependencies: @@ -992,6 +1123,15 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-direction@1.1.0': + resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dismissable-layer@1.0.5': resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} peerDependencies: @@ -1005,6 +1145,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dismissable-layer@1.1.0': + resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-focus-guards@1.0.1': resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -1041,6 +1194,28 @@ packages: '@types/react': optional: true + '@radix-ui/react-id@1.1.0': + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-navigation-menu@1.2.0': + resolution: {integrity: sha512-OQ8tcwAOR0DhPlSY3e4VMXeHiol7la4PPdJWhhwJiJA+NLX0SaCaonOkRnI3gCDHoZ7Fo7bb/G6q25fRM2Y+3Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popover@1.0.7': resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} peerDependencies: @@ -1093,6 +1268,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-presence@1.1.0': + resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@1.0.3': resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -1106,6 +1294,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-primitive@2.0.0': + resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-separator@1.1.0': + resolution: {integrity: sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.0.2': resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} peerDependencies: @@ -1115,6 +1329,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.1.0': + resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-callback-ref@1.0.1': resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -1124,6 +1347,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-callback-ref@1.1.0': + resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-controllable-state@1.0.1': resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} peerDependencies: @@ -1133,6 +1365,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-controllable-state@1.1.0': + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-escape-keydown@1.0.3': resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} peerDependencies: @@ -1142,6 +1383,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-escape-keydown@1.1.0': + resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-layout-effect@1.0.1': resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} peerDependencies: @@ -1151,6 +1401,24 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-layout-effect@1.1.0': + resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.0': + resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-rect@1.0.1': resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==} peerDependencies: @@ -1169,6 +1437,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-visually-hidden@1.1.0': + resolution: {integrity: sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/rect@1.0.1': resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} @@ -1449,6 +1730,9 @@ packages: '@types/react@18.2.74': resolution: {integrity: sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==} + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/scheduler@0.16.8': resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} @@ -2636,6 +2920,11 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lucide-react@0.397.0: + resolution: {integrity: sha512-rUcbRY5jFP/4za/OJvaRUUmdPsPb940Tw9zE1ehrRZmr9JnkDcW8OV3POR3XfEAAMDkssiTc5IWBFv8Y//pkDQ==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.5: resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} engines: {node: '>=12'} @@ -2993,10 +3282,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.32: - resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} @@ -4798,6 +5083,8 @@ snapshots: dependencies: '@babel/runtime': 7.24.4 + '@radix-ui/primitive@1.1.0': {} + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4808,6 +5095,28 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-collection@1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4822,6 +5131,19 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-context@1.0.1(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4836,6 +5158,19 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-context@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-context@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.23.9 @@ -4882,6 +5217,35 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.3)(react@18.2.0) + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.3.3)(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-direction@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4910,20 +5274,54 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.42)(react@18.2.0)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.3)(react@18.2.0) react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.42 + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.42)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.2.42 + + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.74)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 react: 18.2.0 optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4948,6 +5346,18 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-icons@1.3.0(react@18.2.0)': dependencies: react: 18.2.0 @@ -4968,6 +5378,43 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-id@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-id@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-navigation-menu@1.2.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -4992,6 +5439,30 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.3)(react@18.2.0) + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.3.3)(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5011,6 +5482,25 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5031,6 +5521,16 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5053,6 +5553,27 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-presence@1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5073,6 +5594,34 @@ snapshots: '@types/react': 18.2.74 '@types/react-dom': 18.2.24 + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + + '@radix-ui/react-separator@1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/react-slot@1.0.2(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.23.9 @@ -5089,6 +5638,21 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-slot@1.0.2(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-slot@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.23.9 @@ -5103,6 +5667,19 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.23.9 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5119,6 +5696,21 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.23.9 @@ -5135,6 +5727,21 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.42)(react@18.2.0)': dependencies: '@babel/runtime': 7.23.9 @@ -5149,6 +5756,25 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.23.9 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.3)(react@18.2.0)': + dependencies: + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.74)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5157,6 +5783,14 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-rect@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/rect': 1.0.1 + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + '@radix-ui/react-use-size@1.0.1(@types/react@18.2.74)(react@18.2.0)': dependencies: '@babel/runtime': 7.24.4 @@ -5165,6 +5799,23 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + '@radix-ui/react-use-size@1.0.1(@types/react@18.3.3)(react@18.2.0)': + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.2.0) + react: 18.2.0 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.2.24 + '@radix-ui/rect@1.0.1': dependencies: '@babel/runtime': 7.24.4 @@ -5408,11 +6059,11 @@ snapshots: '@types/react-dom@18.2.17': dependencies: - '@types/react': 18.2.42 + '@types/react': 18.2.74 '@types/react-dom@18.2.24': dependencies: - '@types/react': 18.2.74 + '@types/react': 18.3.3 '@types/react@18.2.42': dependencies: @@ -5425,6 +6076,11 @@ snapshots: '@types/prop-types': 15.7.11 csstype: 3.1.2 + '@types/react@18.3.3': + dependencies: + '@types/prop-types': 15.7.11 + csstype: 3.1.2 + '@types/scheduler@0.16.8': {} '@types/semver@7.5.6': {} @@ -5475,6 +6131,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@7.5.0(@typescript-eslint/parser@7.5.0(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.5.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/type-utils': 7.5.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.0 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.5.2) + optionalDependencies: + typescript: 5.5.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.2)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 @@ -5501,6 +6177,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@7.5.0(eslint@8.57.0)(typescript@5.5.2)': + dependencies: + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.2) + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.57.0 + optionalDependencies: + typescript: 5.5.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -5540,6 +6229,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@7.5.0(eslint@8.57.0)(typescript@5.5.2)': + dependencies: + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.2) + '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.5.2) + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.57.0 + ts-api-utils: 1.0.3(typescript@5.5.2) + optionalDependencies: + typescript: 5.5.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@6.21.0': {} @@ -5590,6 +6291,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@7.5.0(typescript@5.5.2)': + dependencies: + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4(supports-color@5.5.0) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.5.2) + optionalDependencies: + typescript: 5.5.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.56.0)(typescript@5.5.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) @@ -5633,6 +6349,20 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@7.5.0(eslint@8.57.0)(typescript@5.5.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.5.2) + eslint: 8.57.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -5712,6 +6442,20 @@ snapshots: optionalDependencies: typescript: 5.3.3 + '@vue/language-core@1.8.27(typescript@5.5.2)': + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.21 + '@vue/shared': 3.4.21 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.16 + optionalDependencies: + typescript: 5.5.2 + '@vue/shared@3.4.21': {} '@zk-kit/groth16@0.3.0': @@ -6053,6 +6797,16 @@ snapshots: - '@types/react' - '@types/react-dom' + cmdk@1.0.0(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -6909,6 +7663,10 @@ snapshots: dependencies: yallist: 4.0.0 + lucide-react@0.397.0(react@18.2.0): + dependencies: + react: 18.2.0 + magic-string@0.30.5: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 @@ -7418,12 +8176,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.32: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - postcss@8.4.38: dependencies: nanoid: 3.3.7 @@ -7531,6 +8283,14 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.2.0): + dependencies: + react: 18.2.0 + react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.2.0) + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.3 + react-remove-scroll@2.5.5(@types/react@18.2.42)(react@18.2.0): dependencies: react: 18.2.0 @@ -7553,6 +8313,17 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + react-remove-scroll@2.5.5(@types/react@18.3.3)(react@18.2.0): + dependencies: + react: 18.2.0 + react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.2.0) + tslib: 2.6.2 + use-callback-ref: 1.3.1(@types/react@18.3.3)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.3.3)(react@18.2.0) + optionalDependencies: + '@types/react': 18.3.3 + react-router-dom@6.20.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@remix-run/router': 1.13.1 @@ -7587,6 +8358,15 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + react-style-singleton@2.2.1(@types/react@18.3.3)(react@18.2.0): + dependencies: + get-nonce: 1.0.1 + invariant: 2.2.4 + react: 18.2.0 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.3 + react@18.2.0: dependencies: loose-envify: 1.4.0 @@ -7827,7 +8607,7 @@ snapshots: '@types/stylis': 4.2.4 css-to-react-native: 3.2.0 csstype: 3.1.2 - postcss: 8.4.32 + postcss: 8.4.38 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) shallowequal: 1.1.0 @@ -8043,6 +8823,13 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + use-callback-ref@1.3.1(@types/react@18.3.3)(react@18.2.0): + dependencies: + react: 18.2.0 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.3 + use-deep-compare-effect@1.8.1(react@18.2.0): dependencies: '@babel/runtime': 7.23.9 @@ -8065,6 +8852,14 @@ snapshots: optionalDependencies: '@types/react': 18.2.74 + use-sidecar@1.1.2(@types/react@18.3.3)(react@18.2.0): + dependencies: + detect-node-es: 1.1.0 + react: 18.2.0 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.3 + use-sync-external-store@1.2.0(react@18.2.0): dependencies: react: 18.2.0 @@ -8113,6 +8908,23 @@ snapshots: - rollup - supports-color + vite-plugin-dts@3.8.1(@types/node@20.12.4)(rollup@4.14.0)(typescript@5.5.2)(vite@5.2.8(@types/node@20.12.4)): + dependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@20.12.4) + '@rollup/pluginutils': 5.1.0(rollup@4.14.0) + '@vue/language-core': 1.8.27(typescript@5.5.2) + debug: 4.3.4(supports-color@5.5.0) + kolorist: 1.8.0 + magic-string: 0.30.9 + typescript: 5.5.2 + vue-tsc: 1.8.27(typescript@5.5.2) + optionalDependencies: + vite: 5.2.8(@types/node@20.12.4) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + vite-plugin-node-polyfills@0.17.0(rollup@4.14.0)(vite@5.0.6(@types/node@20.12.4)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.14.0) @@ -8126,7 +8938,7 @@ snapshots: vite@5.0.6(@types/node@20.12.4): dependencies: esbuild: 0.19.8 - postcss: 8.4.32 + postcss: 8.4.38 rollup: 4.6.1 optionalDependencies: '@types/node': 20.12.4 @@ -8155,6 +8967,13 @@ snapshots: semver: 7.5.4 typescript: 5.3.3 + vue-tsc@1.8.27(typescript@5.5.2): + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.5.2) + semver: 7.5.4 + typescript: 5.5.2 + wasmbuilder@0.0.16: {} wasmcurves@0.2.2: diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index 5724869f..00000000 --- a/vite.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; -import { nodePolyfills } from 'vite-plugin-node-polyfills'; - -// https://vitejs.dev/config/ -export default defineConfig({ - // This is needed because qr-image relies on it being here - // https://github.com/alexeyten/qr-image/issues/13#issuecomment-421289572 - plugins: [ - react(), - nodePolyfills({ - include: ['process'], - globals: { - process: true, - }, - }), - ], -}); From 9d5956f4e03d98280a57fbb0ea78e5ebc81a5c3a Mon Sep 17 00:00:00 2001 From: Camilo Vega <59750365+camilovegag@users.noreply.github.com> Date: Tue, 9 Jul 2024 08:32:28 -0500 Subject: [PATCH 3/9] 642 change front end icons to lucide (#664) * Replace icons at header * Create Icon component * Change back arrow icon * Change comments icon to lucide icon * Keep icon size at 24px * Change copy icon * Change trash icon * Change sorting icon * Update thumbs up icon * Delete unused svgs * Update heart and sqrt icon * Update plurality score icon * Remove unused assets --- .../berlin/public/icons/arrow-back-dark.svg | 3 - .../berlin/public/icons/arrow-back-light.svg | 3 - packages/berlin/public/icons/badge-bronze.svg | 10 - packages/berlin/public/icons/badge-gold.svg | 10 - packages/berlin/public/icons/badge-silver.svg | 10 - .../berlin/public/icons/comments-dark.svg | 3 - .../berlin/public/icons/comments-light.svg | 3 - packages/berlin/public/icons/copy-dark.svg | 3 - packages/berlin/public/icons/copy-light.svg | 3 - .../berlin/public/icons/decentralized.svg | 3 - packages/berlin/public/icons/filter-dark.svg | 3 - packages/berlin/public/icons/filter-light.svg | 3 - packages/berlin/public/icons/heart-empty.svg | 61 ------ packages/berlin/public/icons/heart-full.svg | 59 ------ packages/berlin/public/icons/money-dark.svg | 3 - packages/berlin/public/icons/money-light.svg | 3 - .../berlin/public/icons/plurality-score.svg | 193 +----------------- packages/berlin/public/icons/plurality.svg | 10 - packages/berlin/public/icons/research.svg | 3 - packages/berlin/public/icons/sort-dark.svg | 3 - packages/berlin/public/icons/sort-light.svg | 3 - packages/berlin/public/icons/sqrt-dark.svg | 3 - packages/berlin/public/icons/sqrt-light.svg | 3 - .../berlin/public/icons/thumb-up-active.svg | 3 - .../berlin/public/icons/thumb-up-dark.svg | 3 - .../berlin/public/icons/thumb-up-light.svg | 3 - packages/berlin/public/icons/toggle-dark.svg | 10 - packages/berlin/public/icons/toggle-light.svg | 10 - packages/berlin/public/icons/trash-dark.svg | 10 - packages/berlin/public/icons/trash-light.svg | 10 - packages/berlin/public/icons/unvote-dark.svg | 3 - packages/berlin/public/icons/unvote-light.svg | 3 - packages/berlin/public/icons/user-dark.svg | 3 - packages/berlin/public/icons/user-light.svg | 3 - packages/berlin/public/icons/vote-dark.svg | 3 - packages/berlin/public/icons/vote-light.svg | 3 - .../src/components/back-button/BackButton.tsx | 14 +- .../columns/cycle-columns/CycleColumns.tsx | 10 +- .../results-columns/ResultsColumns.tsx | 13 +- .../berlin/src/components/header/Header.tsx | 24 +-- .../src/components/icon/Icon.styled.tsx | 12 ++ packages/berlin/src/components/icon/Icon.tsx | 12 ++ packages/berlin/src/components/icon/index.ts | 1 + .../src/components/option-card/OptionCard.tsx | 44 ++-- .../src/components/secret-code/SecretCode.tsx | 18 +- .../tables/comment-table/CommentsTable.tsx | 30 +-- .../tables/groups-table/GroupsTable.tsx | 21 +- .../tables/results-table/ResultsTable.tsx | 36 ++-- packages/berlin/src/pages/Comments.tsx | 32 ++- packages/berlin/src/pages/Cycle.tsx | 9 +- 50 files changed, 125 insertions(+), 619 deletions(-) delete mode 100644 packages/berlin/public/icons/arrow-back-dark.svg delete mode 100644 packages/berlin/public/icons/arrow-back-light.svg delete mode 100644 packages/berlin/public/icons/badge-bronze.svg delete mode 100644 packages/berlin/public/icons/badge-gold.svg delete mode 100644 packages/berlin/public/icons/badge-silver.svg delete mode 100644 packages/berlin/public/icons/comments-dark.svg delete mode 100644 packages/berlin/public/icons/comments-light.svg delete mode 100644 packages/berlin/public/icons/copy-dark.svg delete mode 100644 packages/berlin/public/icons/copy-light.svg delete mode 100644 packages/berlin/public/icons/decentralized.svg delete mode 100644 packages/berlin/public/icons/filter-dark.svg delete mode 100644 packages/berlin/public/icons/filter-light.svg delete mode 100644 packages/berlin/public/icons/heart-empty.svg delete mode 100644 packages/berlin/public/icons/heart-full.svg delete mode 100644 packages/berlin/public/icons/money-dark.svg delete mode 100644 packages/berlin/public/icons/money-light.svg delete mode 100644 packages/berlin/public/icons/plurality.svg delete mode 100644 packages/berlin/public/icons/research.svg delete mode 100644 packages/berlin/public/icons/sort-dark.svg delete mode 100644 packages/berlin/public/icons/sort-light.svg delete mode 100644 packages/berlin/public/icons/sqrt-dark.svg delete mode 100644 packages/berlin/public/icons/sqrt-light.svg delete mode 100644 packages/berlin/public/icons/thumb-up-active.svg delete mode 100644 packages/berlin/public/icons/thumb-up-dark.svg delete mode 100644 packages/berlin/public/icons/thumb-up-light.svg delete mode 100644 packages/berlin/public/icons/toggle-dark.svg delete mode 100644 packages/berlin/public/icons/toggle-light.svg delete mode 100644 packages/berlin/public/icons/trash-dark.svg delete mode 100644 packages/berlin/public/icons/trash-light.svg delete mode 100644 packages/berlin/public/icons/unvote-dark.svg delete mode 100644 packages/berlin/public/icons/unvote-light.svg delete mode 100644 packages/berlin/public/icons/user-dark.svg delete mode 100644 packages/berlin/public/icons/user-light.svg delete mode 100644 packages/berlin/public/icons/vote-dark.svg delete mode 100644 packages/berlin/public/icons/vote-light.svg create mode 100644 packages/berlin/src/components/icon/Icon.styled.tsx create mode 100644 packages/berlin/src/components/icon/Icon.tsx create mode 100644 packages/berlin/src/components/icon/index.ts diff --git a/packages/berlin/public/icons/arrow-back-dark.svg b/packages/berlin/public/icons/arrow-back-dark.svg deleted file mode 100644 index 52ea50fc..00000000 --- a/packages/berlin/public/icons/arrow-back-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/arrow-back-light.svg b/packages/berlin/public/icons/arrow-back-light.svg deleted file mode 100644 index ee3b714d..00000000 --- a/packages/berlin/public/icons/arrow-back-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/badge-bronze.svg b/packages/berlin/public/icons/badge-bronze.svg deleted file mode 100644 index da7b9267..00000000 --- a/packages/berlin/public/icons/badge-bronze.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/badge-gold.svg b/packages/berlin/public/icons/badge-gold.svg deleted file mode 100644 index 26df3ab5..00000000 --- a/packages/berlin/public/icons/badge-gold.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/badge-silver.svg b/packages/berlin/public/icons/badge-silver.svg deleted file mode 100644 index 1c1c2657..00000000 --- a/packages/berlin/public/icons/badge-silver.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/comments-dark.svg b/packages/berlin/public/icons/comments-dark.svg deleted file mode 100644 index e5705f47..00000000 --- a/packages/berlin/public/icons/comments-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/comments-light.svg b/packages/berlin/public/icons/comments-light.svg deleted file mode 100644 index 6d0f4b6a..00000000 --- a/packages/berlin/public/icons/comments-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/copy-dark.svg b/packages/berlin/public/icons/copy-dark.svg deleted file mode 100644 index 519477c9..00000000 --- a/packages/berlin/public/icons/copy-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/copy-light.svg b/packages/berlin/public/icons/copy-light.svg deleted file mode 100644 index c62ba036..00000000 --- a/packages/berlin/public/icons/copy-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/decentralized.svg b/packages/berlin/public/icons/decentralized.svg deleted file mode 100644 index 7e2db8d7..00000000 --- a/packages/berlin/public/icons/decentralized.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/filter-dark.svg b/packages/berlin/public/icons/filter-dark.svg deleted file mode 100644 index c25336b7..00000000 --- a/packages/berlin/public/icons/filter-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/filter-light.svg b/packages/berlin/public/icons/filter-light.svg deleted file mode 100644 index da7218a9..00000000 --- a/packages/berlin/public/icons/filter-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/heart-empty.svg b/packages/berlin/public/icons/heart-empty.svg deleted file mode 100644 index 1ad3527f..00000000 --- a/packages/berlin/public/icons/heart-empty.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/berlin/public/icons/heart-full.svg b/packages/berlin/public/icons/heart-full.svg deleted file mode 100644 index 6099f875..00000000 --- a/packages/berlin/public/icons/heart-full.svg +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/berlin/public/icons/money-dark.svg b/packages/berlin/public/icons/money-dark.svg deleted file mode 100644 index 52386eca..00000000 --- a/packages/berlin/public/icons/money-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/money-light.svg b/packages/berlin/public/icons/money-light.svg deleted file mode 100644 index 361531ef..00000000 --- a/packages/berlin/public/icons/money-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/plurality-score.svg b/packages/berlin/public/icons/plurality-score.svg index 9a07c3d4..fe4f94cf 100644 --- a/packages/berlin/public/icons/plurality-score.svg +++ b/packages/berlin/public/icons/plurality-score.svg @@ -1,190 +1,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/packages/berlin/public/icons/plurality.svg b/packages/berlin/public/icons/plurality.svg deleted file mode 100644 index bea7c8f7..00000000 --- a/packages/berlin/public/icons/plurality.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/research.svg b/packages/berlin/public/icons/research.svg deleted file mode 100644 index 303a31bb..00000000 --- a/packages/berlin/public/icons/research.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/sort-dark.svg b/packages/berlin/public/icons/sort-dark.svg deleted file mode 100644 index e8b02d4f..00000000 --- a/packages/berlin/public/icons/sort-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/sort-light.svg b/packages/berlin/public/icons/sort-light.svg deleted file mode 100644 index 8e3edc37..00000000 --- a/packages/berlin/public/icons/sort-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/sqrt-dark.svg b/packages/berlin/public/icons/sqrt-dark.svg deleted file mode 100644 index eb548d54..00000000 --- a/packages/berlin/public/icons/sqrt-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/sqrt-light.svg b/packages/berlin/public/icons/sqrt-light.svg deleted file mode 100644 index 200a9ded..00000000 --- a/packages/berlin/public/icons/sqrt-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/thumb-up-active.svg b/packages/berlin/public/icons/thumb-up-active.svg deleted file mode 100644 index dff25672..00000000 --- a/packages/berlin/public/icons/thumb-up-active.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/thumb-up-dark.svg b/packages/berlin/public/icons/thumb-up-dark.svg deleted file mode 100644 index 799d09a5..00000000 --- a/packages/berlin/public/icons/thumb-up-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/thumb-up-light.svg b/packages/berlin/public/icons/thumb-up-light.svg deleted file mode 100644 index ffc6acff..00000000 --- a/packages/berlin/public/icons/thumb-up-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/toggle-dark.svg b/packages/berlin/public/icons/toggle-dark.svg deleted file mode 100644 index 54042f33..00000000 --- a/packages/berlin/public/icons/toggle-dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/toggle-light.svg b/packages/berlin/public/icons/toggle-light.svg deleted file mode 100644 index 36a2a00c..00000000 --- a/packages/berlin/public/icons/toggle-light.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/trash-dark.svg b/packages/berlin/public/icons/trash-dark.svg deleted file mode 100644 index e72f2c26..00000000 --- a/packages/berlin/public/icons/trash-dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/trash-light.svg b/packages/berlin/public/icons/trash-light.svg deleted file mode 100644 index 6b9b5d0c..00000000 --- a/packages/berlin/public/icons/trash-light.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/berlin/public/icons/unvote-dark.svg b/packages/berlin/public/icons/unvote-dark.svg deleted file mode 100644 index 2f63eaef..00000000 --- a/packages/berlin/public/icons/unvote-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/unvote-light.svg b/packages/berlin/public/icons/unvote-light.svg deleted file mode 100644 index 523a3ad4..00000000 --- a/packages/berlin/public/icons/unvote-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/user-dark.svg b/packages/berlin/public/icons/user-dark.svg deleted file mode 100644 index 22ded840..00000000 --- a/packages/berlin/public/icons/user-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/user-light.svg b/packages/berlin/public/icons/user-light.svg deleted file mode 100644 index d0daf501..00000000 --- a/packages/berlin/public/icons/user-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/vote-dark.svg b/packages/berlin/public/icons/vote-dark.svg deleted file mode 100644 index 9c1eb89d..00000000 --- a/packages/berlin/public/icons/vote-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/public/icons/vote-light.svg b/packages/berlin/public/icons/vote-light.svg deleted file mode 100644 index 22404063..00000000 --- a/packages/berlin/public/icons/vote-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/berlin/src/components/back-button/BackButton.tsx b/packages/berlin/src/components/back-button/BackButton.tsx index afb0c7a2..b6e47541 100644 --- a/packages/berlin/src/components/back-button/BackButton.tsx +++ b/packages/berlin/src/components/back-button/BackButton.tsx @@ -1,6 +1,6 @@ import { useNavigate } from 'react-router-dom'; -import { useAppStore } from '../../store'; -import IconButton from '../icon-button'; +import { ArrowLeft } from 'lucide-react'; +import Icon from '../icon'; type BackButtonProps = { fallbackRoute?: string; @@ -8,7 +8,6 @@ type BackButtonProps = { function BackButton({ fallbackRoute }: BackButtonProps) { const navigate = useNavigate(); - const theme = useAppStore((state) => state.theme); const handleBackClick = () => { if (fallbackRoute) { @@ -19,12 +18,9 @@ function BackButton({ fallbackRoute }: BackButtonProps) { }; return ( - + + + ); } diff --git a/packages/berlin/src/components/columns/cycle-columns/CycleColumns.tsx b/packages/berlin/src/components/columns/cycle-columns/CycleColumns.tsx index f939be67..c1161717 100644 --- a/packages/berlin/src/components/columns/cycle-columns/CycleColumns.tsx +++ b/packages/berlin/src/components/columns/cycle-columns/CycleColumns.tsx @@ -1,6 +1,8 @@ +import { Heart } from 'lucide-react'; import IconButton from '../../icon-button'; import { Body } from '../../typography/Body.styled'; import { Affiliation, Lead, Card, Hearts, Proposal, Plurality } from './CycleColumns.styled'; +import Icon from '../../icon'; type CycleColumnsProps = { onColumnClick: (column: string) => void; @@ -20,11 +22,9 @@ function CycleColumns({ onColumnClick, showScore }: CycleColumnsProps) { Affiliation onColumnClick('numOfVotes')}> - + + + {showScore && ( onColumnClick('voteScore')}> diff --git a/packages/berlin/src/components/columns/results-columns/ResultsColumns.tsx b/packages/berlin/src/components/columns/results-columns/ResultsColumns.tsx index 7d6098ca..d472ca93 100644 --- a/packages/berlin/src/components/columns/results-columns/ResultsColumns.tsx +++ b/packages/berlin/src/components/columns/results-columns/ResultsColumns.tsx @@ -1,3 +1,4 @@ +import { Heart, Radical } from 'lucide-react'; import { useAppStore } from '../../../store'; import IconButton from '../../icon-button'; import { Bold } from '../../typography/Bold.styled'; @@ -12,16 +13,8 @@ function ResultsColumns({ $showFunding }: ResultsColumnsType) { return ( Title - - + + )} - navigate('/account')} - icon={{ src: `/icons/user-${theme}.svg`, alt: 'User' }} - $color="primary" - $height={20} - $width={20} - /> + ) : ( Login with Zupass @@ -149,14 +144,9 @@ function Header() {
  • - - Toggle theme icon - +
  • diff --git a/packages/berlin/src/components/icon/Icon.styled.tsx b/packages/berlin/src/components/icon/Icon.styled.tsx new file mode 100644 index 00000000..e7644786 --- /dev/null +++ b/packages/berlin/src/components/icon/Icon.styled.tsx @@ -0,0 +1,12 @@ +import styled from 'styled-components'; + +export const StyledIcon = styled.div` + cursor: pointer; + height: 1.5rem; + width: 1.5rem; + + &:hover { + opacity: 0.8; + transition: opacity 0.2s ease-in; + } +`; diff --git a/packages/berlin/src/components/icon/Icon.tsx b/packages/berlin/src/components/icon/Icon.tsx new file mode 100644 index 00000000..ba3d553c --- /dev/null +++ b/packages/berlin/src/components/icon/Icon.tsx @@ -0,0 +1,12 @@ +import React, { forwardRef } from 'react'; +import { StyledIcon } from './Icon.styled'; + +type IconProps = { + children: React.ReactNode; +}; + +const Icon = forwardRef(({ children }, ref) => ( + {children} +)); + +export default Icon; diff --git a/packages/berlin/src/components/icon/index.ts b/packages/berlin/src/components/icon/index.ts new file mode 100644 index 00000000..dc6b45c3 --- /dev/null +++ b/packages/berlin/src/components/icon/index.ts @@ -0,0 +1 @@ +export { default } from './Icon'; diff --git a/packages/berlin/src/components/option-card/OptionCard.tsx b/packages/berlin/src/components/option-card/OptionCard.tsx index 53d10b7f..b1ecb8d1 100644 --- a/packages/berlin/src/components/option-card/OptionCard.tsx +++ b/packages/berlin/src/components/option-card/OptionCard.tsx @@ -1,3 +1,25 @@ +// React and third-party libraries +import { MessageSquareText } from 'lucide-react'; +import { useMemo, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; +import Markdown from 'react-markdown'; + +// Store +import { useAppStore } from '../../store'; + +// API +import { fetchOptionUsers, GetCycleResponse } from 'api'; + +// Components +import { Body } from '../typography/Body.styled'; +import { Bold } from '../typography/Bold.styled'; +import { FlexColumn } from '../containers/FlexColumn.styled'; +import IconButton from '../icon-button'; +import Link from '../link'; +import Icon from '../icon'; + +// Styled Components import { Affiliation, ArrowDownIcon, @@ -12,17 +34,6 @@ import { Votes, VotesIcon, } from './OptionCard.styled'; -import { Body } from '../typography/Body.styled'; -import { Bold } from '../typography/Bold.styled'; -import { FlexColumn } from '../containers/FlexColumn.styled'; -import { fetchOptionUsers, GetCycleResponse } from 'api'; -import { useAppStore } from '../../store'; -import { useNavigate, useParams } from 'react-router-dom'; -import { useQuery } from '@tanstack/react-query'; -import { useMemo, useState } from 'react'; -import IconButton from '../icon-button'; -import Markdown from 'react-markdown'; -import Link from '../link'; type OptionCardProps = { option: GetCycleResponse['forumQuestions'][number]['questionOptions'][number]; @@ -173,14 +184,9 @@ function OptionCard({ {option.optionSubTitle} )} - + + +
    diff --git a/packages/berlin/src/components/secret-code/SecretCode.tsx b/packages/berlin/src/components/secret-code/SecretCode.tsx index aeb10e18..e186af60 100644 --- a/packages/berlin/src/components/secret-code/SecretCode.tsx +++ b/packages/berlin/src/components/secret-code/SecretCode.tsx @@ -1,11 +1,10 @@ -import toast from 'react-hot-toast'; -import { useAppStore } from '../../store'; - import { Body } from '../typography/Body.styled'; +import { Copy } from 'lucide-react'; import { FlexRow } from '../containers/FlexRow.styled'; import { SecretCodeContainer } from './SecretCode.styled'; import { Subtitle } from '../typography/Subtitle.styled'; -import IconButton from '../icon-button'; +import Icon from '../icon'; +import toast from 'react-hot-toast'; type SecretCodeProps = { groupName: string; @@ -13,8 +12,6 @@ type SecretCodeProps = { }; function SecretCode({ groupName, secretCode }: SecretCodeProps) { - const theme = useAppStore((state) => state.theme); - const handleCopyButtonClick = () => { navigator.clipboard.writeText(secretCode); toast.success(`Secret code ${secretCode} copied to clipboard`); @@ -24,12 +21,9 @@ function SecretCode({ groupName, secretCode }: SecretCodeProps) { Access code for {groupName} research group {secretCode} - + + + ); diff --git a/packages/berlin/src/components/tables/comment-table/CommentsTable.tsx b/packages/berlin/src/components/tables/comment-table/CommentsTable.tsx index 6580aac1..4a5801f0 100644 --- a/packages/berlin/src/components/tables/comment-table/CommentsTable.tsx +++ b/packages/berlin/src/components/tables/comment-table/CommentsTable.tsx @@ -1,4 +1,5 @@ // React and third-party libraries +import { ThumbsUp, Trash } from 'lucide-react'; import { useEffect, useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useParams } from 'react-router-dom'; @@ -9,14 +10,11 @@ import { GetCommentsResponse, deleteComment, deleteLike, fetchCommentLikes, post // Hooks import useUser from '../../../hooks/useUser'; -// Store -import { useAppStore } from '../../../store'; - // Components import { FlexRow } from '../../containers/FlexRow.styled'; import Button from '../../button'; import Dialog from '../../dialog'; -import IconButton from '../../icon-button'; +import Icon from '../../icon'; // Styled Components import { Author, Card, Comment, FormattedDate } from './CommentsTable.styled'; @@ -27,7 +25,6 @@ type CommentsTableProps = { function CommentsTable({ comment }: CommentsTableProps) { const { optionId } = useParams(); - const theme = useAppStore((state) => state.theme); const queryClient = useQueryClient(); const { user } = useUser(); @@ -114,16 +111,7 @@ function CommentsTable({ comment }: CommentsTableProps) { onClick={handleLikeClick} style={{ userSelect: 'none' }} > - + {isCommentLiked ? : } @@ -131,13 +119,11 @@ function CommentsTable({ comment }: CommentsTableProps) { {comment.user?.username === user?.username && ( +
    + + + +
    } title="Are you sure?" description="This action cannot be undone. This will permanently delete your comment from our servers." diff --git a/packages/berlin/src/components/tables/groups-table/GroupsTable.tsx b/packages/berlin/src/components/tables/groups-table/GroupsTable.tsx index 192cd47c..64edd8eb 100644 --- a/packages/berlin/src/components/tables/groups-table/GroupsTable.tsx +++ b/packages/berlin/src/components/tables/groups-table/GroupsTable.tsx @@ -1,4 +1,5 @@ // React and third-party libraries +import { Copy } from 'lucide-react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import toast from 'react-hot-toast'; @@ -7,8 +8,8 @@ import toast from 'react-hot-toast'; import { deleteUsersToGroups, fetchGroupMembers, - GetUsersToGroupsResponse, fetchGroupRegistrations, + GetUsersToGroupsResponse, } from 'api'; // Hooks @@ -16,14 +17,15 @@ import { useAppStore } from '../../../store'; import useUser from '../../../hooks/useUser'; // Components +import { Body } from '../../typography/Body.styled'; +import { Bold } from '../../typography/Bold.styled'; import { Card, Group, GroupProposal, Secret } from './GroupsTable.styled'; +import { FlexColumn } from '../../containers/FlexColumn.styled'; +import { FlexRow } from '../../containers/FlexRow.styled'; import Button from '../../button'; import Dialog from '../../dialog'; +import Icon from '../../icon'; import IconButton from '../../icon-button'; -import { Body } from '../../typography/Body.styled'; -import { FlexRow } from '../../containers/FlexRow.styled'; -import { FlexColumn } from '../../containers/FlexColumn.styled'; -import { Bold } from '../../typography/Bold.styled'; interface GroupCardProps { userToGroup: GetUsersToGroupsResponse[0]; @@ -91,12 +93,9 @@ function GroupCard({ userToGroup, theme, onLeaveGroup }: GroupCardProps) { {userToGroup.group.secret ? ( {userToGroup.group.secret} - handleCopyButtonClick(userToGroup.group.secret || '')} - icon={{ src: `/icons/copy-${theme}.svg`, alt: 'Copy icon' }} - $color="secondary" - $padding={4} - /> + + handleCopyButtonClick(userToGroup.group.secret || '')} /> + ) : ( No secret diff --git a/packages/berlin/src/components/tables/results-table/ResultsTable.tsx b/packages/berlin/src/components/tables/results-table/ResultsTable.tsx index b4eb4012..2f21d4f2 100644 --- a/packages/berlin/src/components/tables/results-table/ResultsTable.tsx +++ b/packages/berlin/src/components/tables/results-table/ResultsTable.tsx @@ -1,6 +1,9 @@ // React and third-party libraries -import { useQuery } from '@tanstack/react-query'; +import { Heart, MessageSquareText, Radical } from 'lucide-react'; import { useMemo } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; +import Markdown from 'react-markdown'; // API import { fetchOptionUsers, fetchRegistrationData, fetchRegistrationFields } from 'api'; @@ -9,17 +12,15 @@ import { fetchOptionUsers, fetchRegistrationData, fetchRegistrationFields } from import { useAppStore } from '../../../store'; // Components +import { Body } from '../../typography/Body.styled'; +import { Bold } from '../../typography/Bold.styled'; import { FlexColumn } from '../../containers/FlexColumn.styled'; import { FlexRow } from '../../containers/FlexRow.styled'; import IconButton from '../../icon-button'; -import { Body } from '../../typography/Body.styled'; -import { Bold } from '../../typography/Bold.styled'; +import Link from '../../link'; // Styled Components -import { useNavigate } from 'react-router-dom'; import { Card, Funding, Icon, Plurality, TitleContainer } from './ResultsTable.styled'; -import Markdown from 'react-markdown'; -import Link from '../../link'; type ResultsTableProps = { $expanded: boolean; @@ -105,21 +106,13 @@ function ResultsTable({ $expanded, option, onClick, cycleId, eventId }: ResultsT - + {option.allocatedHearts} - + {formattedQuadraticScore} @@ -188,14 +181,9 @@ function ResultsTable({ $expanded, option, onClick, cycleId, eventId }: ResultsT Voter affiliations: {option.listOfGroupNames.join(', ')} - + + + diff --git a/packages/berlin/src/pages/Comments.tsx b/packages/berlin/src/pages/Comments.tsx index d30167bc..1d7e49c3 100644 --- a/packages/berlin/src/pages/Comments.tsx +++ b/packages/berlin/src/pages/Comments.tsx @@ -1,4 +1,5 @@ // React and third-party libraries +import { ArrowDownUp } from 'lucide-react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useParams } from 'react-router-dom'; import { useMemo, useState } from 'react'; @@ -17,9 +18,6 @@ import { fetchOption, fetchComments, postComment, fetchOptionUsers } from 'api'; // handleLocalVote, // } from '../utils/voting'; -// Store -import { useAppStore } from '../store'; - // Components import { Body } from '../components/typography/Body.styled'; import { Bold } from '../components/typography/Bold.styled'; @@ -29,16 +27,15 @@ import { Form } from '../components/containers/Form.styled'; import { Subtitle } from '../components/typography/Subtitle.styled'; import BackButton from '../components/back-button'; import Button from '../components/button'; -import CommentsTable from '../components/tables/comment-table'; import CommentsColumns from '../components/columns/comments-columns'; -import IconButton from '../components/icon-button'; +import CommentsTable from '../components/tables/comment-table'; +import Icon from '../components/icon'; import Textarea from '../components/textarea'; // import { INITIAL_HEARTS } from '../utils/constants'; // type LocalUserVotes = { optionId: string; numOfVotes: number }[]; function Comments() { - const theme = useAppStore((state) => state.theme); const queryClient = useQueryClient(); const { optionId } = useParams(); // const { user } = useUser(); @@ -223,20 +220,17 @@ function Comments() { <> Total comments ({sortedComments.length}) -
    + + setSortOrder((prevOrder) => (prevOrder === 'asc' ? 'desc' : 'asc'))} + > Sort - setSortOrder((prevOrder) => (prevOrder === 'asc' ? 'desc' : 'asc'))} - icon={{ - src: `/icons/sort-${theme}.svg`, - alt: 'Sort icon', - }} - $padding={4} - $color="secondary" - $height={24} - $width={24} - /> -
    + + + +
    diff --git a/packages/berlin/src/pages/Cycle.tsx b/packages/berlin/src/pages/Cycle.tsx index a625aa85..72626f10 100644 --- a/packages/berlin/src/pages/Cycle.tsx +++ b/packages/berlin/src/pages/Cycle.tsx @@ -33,6 +33,7 @@ import Button from '../components/button'; import CycleColumns from '../components/columns/cycle-columns'; import OptionCard from '../components/option-card'; import { FINAL_QUESTION_TITLE, FIVE_MINUTES_IN_SECONDS, INITIAL_HEARTS } from '../utils/constants'; +import { Heart } from 'lucide-react'; type Order = 'asc' | 'desc'; type LocalUserVotes = { optionId: string; numOfVotes: number }[]; @@ -311,13 +312,7 @@ function Cycle() { {Array.from({ length: INITIAL_HEARTS }).map((_, id) => ( - {id + ))} + + setIsPopoverOpen(false)} + > + + + + + No results found. + + + +
    + +
    + (Select All) +
    + {options.map((option) => { + const isSelected = defaultValue.includes(option.value); + return ( + toggleOption(option.value)} + style={{ pointerEvents: 'auto', opacity: 1 }} + className="cursor-pointer rounded-none p-3 text-[var(--color-black)] data-[selected=true]:bg-[var(--color-gray)] data-[selected=true]:text-[var(--color-black)]" + > +
    + +
    + {option.icon && ( + + )} + {option.label} +
    + ); + })} +
    +
    +
    +
    + {animation > 0 && defaultValue.length > 0 && ( + setIsAnimating(!isAnimating)} + /> + )} + + ); + }, +); + +MultiSelect.displayName = 'MultiSelect'; diff --git a/packages/berlin/src/components/multi-select/index.ts b/packages/berlin/src/components/multi-select/index.ts new file mode 100644 index 00000000..f1f7f3d3 --- /dev/null +++ b/packages/berlin/src/components/multi-select/index.ts @@ -0,0 +1 @@ +export * from './MultiSelect'; diff --git a/packages/berlin/src/pages/Register.tsx b/packages/berlin/src/pages/Register.tsx index d9b39ded..56cfbc01 100644 --- a/packages/berlin/src/pages/Register.tsx +++ b/packages/berlin/src/pages/Register.tsx @@ -2,7 +2,7 @@ import { useMutation, useQueries, useQuery, useQueryClient } from '@tanstack/react-query'; import { useEffect, useMemo, useState } from 'react'; import ContentLoader from 'react-content-loader'; -import { useForm } from 'react-hook-form'; +import { UseFormReturn, useForm } from 'react-hook-form'; import toast from 'react-hot-toast'; import { useNavigate, useParams } from 'react-router-dom'; @@ -12,6 +12,7 @@ import { GetGroupCategoriesResponse, GetRegistrationsResponseType, GetUsersToGroupsResponse, + deleteUsersToGroups, fetchEvent, fetchEventGroupCategories, fetchGroups, @@ -22,7 +23,6 @@ import { postRegistration, postUsersToGroups, putRegistration, - putUsersToGroups, type GetRegistrationDataResponse, type GetRegistrationFieldsResponse, type GetRegistrationResponseType, @@ -33,19 +33,17 @@ import { import useUser from '../hooks/useUser'; // Components +import Button from '../components/button'; import { FlexColumn } from '../components/containers/FlexColumn.styled'; -import { FlexRow } from '../components/containers/FlexRow.styled'; import { Form } from '../components/containers/Form.styled'; -import { FormInput } from '../components/form'; -import { SafeArea } from '../layout/Layout.styled'; -import { Subtitle } from '../components/typography/Subtitle.styled'; -import Button from '../components/button'; -import Dots from '../components/dots'; -import Label from '../components/typography/Label'; +import { FormInput, SelectInput } from '../components/form'; import Select from '../components/select'; +import Label from '../components/typography/Label'; +import { Subtitle } from '../components/typography/Subtitle.styled'; +import { SafeArea } from '../layout/Layout.styled'; +import { Carousel } from '../components/carousel'; function Register() { - const [step, setStep] = useState(null); const { user, isLoading } = useUser(); const { eventId } = useParams(); const [selectedRegistrationFormKey, setSelectedRegistrationFormKey] = useState< @@ -125,21 +123,6 @@ function Register() { }, }); - const showRegistrationForm = ({ - registrationId, - selectedRegistrationFormKey, - }: { - registrationId?: string; - selectedRegistrationFormKey?: string; - }) => { - if (selectedRegistrationFormKey === 'create' && !registrationId) { - // show create registration form - return true; - } - - return registrationId === selectedRegistrationFormKey; - }; - const onRegistrationFormCreate = (newRegistrationId: string) => { // select the newly created registration form setSelectedRegistrationFormKey(newRegistrationId); @@ -149,78 +132,197 @@ function Register() { return Loading...; } - const getRecentStep = (step: number | null, defaultStep: number) => { - if (step === null) { - return defaultStep; + return ( + + + + ); +} + +const CarouselWrapper = ({ + groupCategories, + usersToGroups, + user, + registrations, + selectedRegistrationFormKey, + multipleRegistrationData, + registrationFields, + event, + onRegistrationFormCreate, + setSelectedRegistrationFormKey, +}: { + defaultStep: number; + groupCategories: GetGroupCategoriesResponse | null | undefined; + usersToGroups: GetUsersToGroupsResponse | null | undefined; + user: GetUserResponse | null | undefined; + registrations: GetRegistrationsResponseType | undefined | null; + selectedRegistrationFormKey: string | undefined; + multipleRegistrationData: Record< + string, + { + data: GetRegistrationDataResponse | null | undefined; + loading: boolean; + } + >; + registrationFields: GetRegistrationFieldsResponse | null | undefined; + event: GetEventResponse | null | undefined; + onRegistrationFormCreate: (newRegistrationId: string) => void; + setSelectedRegistrationFormKey: (key: string) => void; +}) => { + const navigate = useNavigate(); + + const queryClient = useQueryClient(); + + const redirectToNextPage = (isApproved: boolean, eventId: string) => { + if (!isApproved) { + navigate(`/events/${eventId}/holding`); } - return step; + navigate(`/events/${eventId}/cycles`); + }; + + const { mutateAsync: postRegistrationMutation, isPending: postRegistrationIsPending } = + useMutation({ + mutationFn: postRegistration, + onSuccess: async (body) => { + if (body) { + toast.success('Registration saved successfully!'); + await queryClient.invalidateQueries({ + queryKey: ['event', body.eventId, 'registrations'], + }); + + // invalidate user registrations, this is for the 1 event use case + // where the authentication is because you are approved to the event + await queryClient.invalidateQueries({ + queryKey: [user?.id, 'registrations'], + }); + } else { + toast.error('Failed to save registration, please try again'); + } + }, + onError: (error) => { + console.error('Error saving registration:', error); + toast.error('Failed to save registration, please try again'); + }, + }); + + const { mutateAsync: updateRegistrationMutation, isPending: updateRegistrationIsPending } = + useMutation({ + mutationFn: putRegistration, + onSuccess: async (body) => { + if (body) { + toast.success('Registration updated successfully!'); + + await queryClient.invalidateQueries({ + queryKey: ['event', event?.id, 'registrations'], + }); + } else { + toast.error('Failed to update registration, please try again'); + } + }, + onError: (error) => { + console.error('Error updating registration:', error); + toast.error('Failed to update registration, please try again'); + }, + }); + + const handleSubmit = async () => { + const foundRegistration = registrations?.at(0); + + if (foundRegistration) { + await updateRegistrationMutation({ + registrationId: foundRegistration.id || '', + body: { + eventId: event?.id || '', + groupId: null, + status: 'DRAFT', + registrationData: [], + }, + }); + } else { + await postRegistrationMutation({ + body: { + eventId: event?.id || '', + groupId: null, + status: 'DRAFT', + registrationData: [], + }, + }); + } }; return ( - - - {getRecentStep(step, defaultStep) === 0 && - groupCategories - ?.filter((groupCategory) => groupCategory.required) - .map((groupCategory) => ( - setStep(1)} - /> - ))} - {getRecentStep(step, defaultStep) === 1 && ( - <> - { + // query registration to check if it is approved + const registrations = await queryClient.fetchQuery({ + queryKey: ['event', event?.id, 'registrations'], + queryFn: () => fetchRegistrations(event?.id || ''), + }); + + redirectToNextPage( + registrations?.some((reg) => reg.status === 'APPROVED') ?? false, + event?.id || '', + ); + }} + steps={[ + { + isEnabled: (groupCategories?.filter((category) => category.required).length ?? 0) > 0, + render: ({ isLastStep, handleStepComplete }) => ( + { + if (updateRegistrationIsPending || postRegistrationIsPending) { + return; + } + + if (isLastStep) { + await handleSubmit(); + } + + await handleStepComplete(); + }} + /> + ), + }, + { + isEnabled: (registrationFields?.length ?? 0) > 0, + render: ({ handleStepComplete }) => ( + - {createRegistrationForms({ registrations, usersToGroups }).map((form, idx) => { - return ( - - ); - })} - - )} - { - // the user is not allowed to go out of the first step - if (defaultStep == 0) { - return; - } - - setStep(i); - }} - /> - - + ), + }, + ]} + /> ); -} +}; + const sortRegistrationsByCreationDate = (registrations: GetRegistrationResponseType[]) => { return [ ...registrations.sort((a, b) => { @@ -260,104 +362,7 @@ const createRegistrationForms = ({ return registrationForms; }; -const SelectEventGroup = ({ - groupCategory, - userToGroups, - user, - afterSubmit, -}: { - userToGroups: GetUsersToGroupsResponse | null | undefined; - groupCategory: GetGroupCategoriesResponse[number] | null | undefined; - user: GetUserResponse | null | undefined; - afterSubmit?: () => void; -}) => { - // fetch all the groups in the category - // show a select with all the groups - // if the user is in a group in that category, show that group as selected - const [newGroup, setNewGroup] = useState(''); - const queryClient = useQueryClient(); - const { data: groups } = useQuery({ - queryKey: ['group-category', groupCategory?.id, 'groups'], - queryFn: () => fetchGroups({ groupCategoryId: groupCategory?.id ?? '' }), - enabled: !!groupCategory?.id, - }); - - const { mutate: postUsersToGroupsMutation } = useMutation({ - mutationFn: postUsersToGroups, - onSuccess: (body) => { - if (!body) { - return; - } - queryClient.invalidateQueries({ queryKey: ['user', user?.id, 'users-to-groups'] }); - toast.success(`Joined group successfully!`); - afterSubmit?.(); - }, - onError: () => { - toast.error('Something went wrong.'); - }, - }); - - const { mutate: putUsersToGroupsMutation } = useMutation({ - mutationFn: putUsersToGroups, - onSuccess: (body) => { - if (!body) { - return; - } - - if ('errors' in body) { - toast.error(body.errors.join(', ')); - return; - } - - queryClient.invalidateQueries({ queryKey: ['user', user?.id, 'users-to-groups'] }); - toast.success(`Updated group successfully!`); - afterSubmit?.(); - }, - onError: () => { - toast.error('Something went wrong.'); - }, - }); - - const userGroup = userToGroups?.find( - (userToGroup) => userToGroup.group.groupCategory?.id === groupCategory?.id, - ); - - const onSubmit = () => { - if (userGroup && newGroup) { - // update the group - putUsersToGroupsMutation({ - groupId: newGroup, - userToGroupId: userGroup.id, - }); - return; - } - - // create a new group - postUsersToGroupsMutation({ groupId: newGroup }); - }; - - return ( - - - ({ @@ -493,7 +498,7 @@ const SelectRegistrationDropdown = ({ ) ); -}; +} const getDefaultValues = (registrationData: GetRegistrationDataResponse | null | undefined) => { return registrationData?.reduce( @@ -522,7 +527,227 @@ const filterRegistrationFields = ( }); }; -function RegisterForm(props: { +function EventGroupsForm({ + groupCategories, + usersToGroups, + user, + onStepComplete, +}: { + groupCategories: GetGroupCategoriesResponse | null | undefined; + usersToGroups: GetUsersToGroupsResponse | null | undefined; + user: GetUserResponse | null | undefined; + onStepComplete?: () => Promise; +}) { + const queryClient = useQueryClient(); + const form = useForm({ + mode: 'all', + // user to groups keyed by group category id + defaultValues: usersToGroups?.reduce( + (acc, userToGroup) => { + if (!userToGroup.group.groupCategoryId) { + return acc; + } + + if (!acc[userToGroup.groupCategoryId ?? '']) { + acc[userToGroup.group.groupCategoryId] = []; + } + + acc[userToGroup.group.groupCategoryId].push(userToGroup.group.id); + return acc; + }, + {} as Record, + ), + }); + + const { mutateAsync: postUsersToGroupsMutation, isPending: postUsersToGroupsIsLoading } = + useMutation({ + mutationFn: postUsersToGroups, + onSuccess: (body) => { + if (!body) { + return; + } + queryClient.invalidateQueries({ queryKey: ['user', user?.id, 'users-to-groups'] }); + }, + onError: () => { + toast.error('Something went wrong.'); + }, + }); + + const { mutateAsync: deleteUsersToGroupsMutation, isPending: deleteUsersToGroupsIsLoading } = + useMutation({ + mutationFn: deleteUsersToGroups, + onSuccess: (body) => { + if (body) { + if ('errors' in body) { + toast.error(body.errors[0]); + return; + } + + queryClient.invalidateQueries({ queryKey: ['user', user?.id, 'users-to-groups'] }); + } + }, + }); + + const onSubmit = async (values: Record) => { + const formGroupIds = Object.values(values).flat(); + const previousGroupIds = usersToGroups?.map((userToGroup) => userToGroup.group.id) || []; + // add groups that are new + // delete groups that are no longer selected + const groupsToAdd = formGroupIds.filter((groupId) => !previousGroupIds.includes(groupId)); + const groupsToDelete = previousGroupIds.filter((groupId) => !formGroupIds.includes(groupId)); + + try { + await Promise.all( + groupsToAdd.map((groupId) => + postUsersToGroupsMutation({ + groupId, + }), + ), + ); + + await Promise.all( + groupsToDelete.map(async (groupId) => { + const userToGroup = usersToGroups?.find( + (userToGroup) => userToGroup.group.id === groupId, + ); + if (userToGroup) { + await deleteUsersToGroupsMutation({ userToGroupId: userToGroup.id }); + } + }), + ); + + await onStepComplete?.(); + } catch (e) { + console.error('Error saving groups:', e); + } + }; + + return ( + + {groupCategories + ?.filter((groupCategory) => groupCategory.required) + .map((groupCategory) => ( + + ))} + + + ); +} + +function SelectEventGroup({ + groupCategory, + form, +}: { + groupCategory: GetGroupCategoriesResponse[number] | null | undefined; + form: UseFormReturn>; +}) { + const { data: groups } = useQuery({ + queryKey: ['group-category', groupCategory?.id, 'groups'], + queryFn: () => fetchGroups({ groupCategoryId: groupCategory?.id ?? '' }), + enabled: !!groupCategory?.id, + }); + + return ( + ({ value: group.id, name: group.name })) || []} + // group category id is the key for the form + // and the form supports multiple groups hence the array key + name={`${groupCategory?.id}.[0]`} + required + /> + ); +} + +function RegistrationForm({ + registrationFields, + event, + multipleRegistrationData, + registrations, + selectedRegistrationFormKey, + user, + usersToGroups, + onRegistrationFormCreate, + onSelectedRegistrationFormKeyChange, + onStepComplete, +}: { + registrations: GetRegistrationsResponseType | undefined | null; + usersToGroups: GetUsersToGroupsResponse | undefined | null; + selectedRegistrationFormKey: string | undefined; + multipleRegistrationData: Record< + string, + { + data: GetRegistrationDataResponse | null | undefined; + loading: boolean; + } + >; + registrationFields: GetRegistrationFieldsResponse | null | undefined; + user: GetUserResponse | null | undefined; + event: GetEventResponse | null | undefined; + onRegistrationFormCreate?: (newRegistrationId: string) => void; + onSelectedRegistrationFormKeyChange: (key: string) => void; + onStepComplete?: () => void; +}) { + const showRegistrationForm = ({ + registrationId, + selectedRegistrationFormKey, + }: { + registrationId?: string; + selectedRegistrationFormKey?: string; + }) => { + if (selectedRegistrationFormKey === 'create' && !registrationId) { + // show create registration form + return true; + } + + return registrationId === selectedRegistrationFormKey; + }; + + return ( + <> + + {createRegistrationForms({ registrations, usersToGroups }).map((form, idx) => { + return ( + + ); + })} + + ); +} + +function DynamicRegistrationFieldsForm(props: { user: GetUserResponse | null | undefined; usersToGroups: GetUsersToGroupsResponse | null | undefined; registrationFields: GetRegistrationFieldsResponse | null | undefined; @@ -534,8 +759,8 @@ function RegisterForm(props: { isLoading: boolean; onRegistrationFormCreate?: (newRegistrationId: string) => void; registrationData: GetRegistrationDataResponse | null | undefined; + onStepComplete?: () => void; }) { - const navigate = useNavigate(); const queryClient = useQueryClient(); // i want to differentiate between when a group is selected and it is not @@ -574,14 +799,6 @@ function RegisterForm(props: { return sortedFields; }, [props.registrationFields, selectedGroupId, prevSelectGroupId]); - const redirectToNextPage = (isApproved: boolean) => { - if (!isApproved) { - navigate(`/events/${props.event?.id}/holding`); - } - - navigate(`/events/${props.event?.id}/cycles`); - }; - const { mutate: mutateRegistrationData, isPending } = useMutation({ mutationFn: postRegistration, onSuccess: async (body) => { @@ -602,7 +819,7 @@ function RegisterForm(props: { props.onRegistrationFormCreate?.(body.id); - redirectToNextPage(body.status === 'APPROVED'); + props.onStepComplete?.(); } else { toast.error('Failed to save registration, please try again'); } @@ -626,7 +843,7 @@ function RegisterForm(props: { queryKey: ['registrations', props.registrationId, 'registration-data'], }); - redirectToNextPage(body.status === 'APPROVED'); + props.onStepComplete?.(); } else { toast.error('Failed to update registration, please try again'); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de659e56..2cccfb5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -913,10 +913,12 @@ packages: '@humanwhocodes/config-array@0.11.13': resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -924,9 +926,11 @@ packages: '@humanwhocodes/object-schema@2.0.1': resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + deprecated: Use @eslint/object-schema instead '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -2599,6 +2603,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -2707,6 +2712,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3466,6 +3472,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true ripemd160@2.0.2: From cbcd1434645f90b62e82a0c3f08932bcc787ed71 Mon Sep 17 00:00:00 2001 From: Martin Benedikt Busch <43137759+MartinBenediktBusch@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:38:10 +0200 Subject: [PATCH 7/9] Text changes (#693) * preliminary landing page changes * text change * add placeholder link * Update favicon * Update footer * Adjust layout to footer changes * add form link --------- Co-authored-by: camilovegag --- packages/berlin/index.html | 4 +- packages/berlin/public/favicon.ico | Bin 29205 -> 16958 bytes packages/berlin/src/data/footer.ts | 26 +--------- packages/berlin/src/data/header.ts | 6 +-- packages/berlin/src/layout/Layout.styled.tsx | 2 +- packages/berlin/src/pages/Landing.tsx | 48 +++++-------------- 6 files changed, 20 insertions(+), 66 deletions(-) diff --git a/packages/berlin/index.html b/packages/berlin/index.html index a22f7821..fafa6d8c 100644 --- a/packages/berlin/index.html +++ b/packages/berlin/index.html @@ -12,9 +12,9 @@ - Plural Research Experiment + Plurality Demo
    diff --git a/packages/berlin/public/favicon.ico b/packages/berlin/public/favicon.ico index 1e7f70fde3a28a7c76f5770590f3774c49bf4f6e..7c1dd24a0f4fa60df9328ede16f0cb64937295cb 100644 GIT binary patch literal 16958 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 diff --git a/packages/berlin/src/data/footer.ts b/packages/berlin/src/data/footer.ts index 70d35fac..605c2134 100644 --- a/packages/berlin/src/data/footer.ts +++ b/packages/berlin/src/data/footer.ts @@ -1,30 +1,6 @@ const footer = { - copy: [ - { id: 0, text: 'A grants program funded by Plurality Labs and the Arbitrum DAO' }, - { id: 1, text: 'Co-sponsored by RadicalXChange, MetaGov & De-Sci Foundation' }, - { id: 2, text: 'Tooling built by Lexicon Governance' }, - ], + copy: [{ id: 0, text: 'Tooling built by Lexicon Governance' }], logos: [ - { - src: `arbitrum`, // src here its just the filename as we render it as `/logo/${src}-{theme}.svg` - alt: 'Arbitrum', - link: 'https://arbitrum.foundation/grants', - }, - { - src: `radicalxchange`, - alt: 'RadicalXChange', - link: 'https://www.radicalxchange.org/', - }, - { - src: `metagov`, - alt: 'MetaGov', - link: 'https://metagov.org/', - }, - { - src: `desci`, - alt: 'De-Sci Foundation', - link: 'https://www.descifoundation.org/', - }, { src: `lexicon`, alt: 'Lexicon Governance', diff --git a/packages/berlin/src/data/header.ts b/packages/berlin/src/data/header.ts index 648dbbe5..b8fab9f1 100644 --- a/packages/berlin/src/data/header.ts +++ b/packages/berlin/src/data/header.ts @@ -1,10 +1,10 @@ const header = { logo: { src: '/logos/logo.png', - alt: 'Plural Research Experiment logo, a prism with an incoming light beam and a rainbow', + alt: 'Lexicon Governance Logo', }, - title: 'Plural Research Experiment', - subtitle: 'An experiment in collective intelligence and innovation', + title: 'Plurality Demo', + subtitle: 'Lexicon Governance', }; export default header; diff --git a/packages/berlin/src/layout/Layout.styled.tsx b/packages/berlin/src/layout/Layout.styled.tsx index f4bf615d..afe51b6f 100644 --- a/packages/berlin/src/layout/Layout.styled.tsx +++ b/packages/berlin/src/layout/Layout.styled.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components'; export const Main = styled.main` margin-inline: auto; - min-height: calc(100vh - 21.5rem); + min-height: calc(100vh - 17.5rem); padding-block: 4rem; width: min(90%, 1080px); `; diff --git a/packages/berlin/src/pages/Landing.tsx b/packages/berlin/src/pages/Landing.tsx index 152a886b..df1522a0 100644 --- a/packages/berlin/src/pages/Landing.tsx +++ b/packages/berlin/src/pages/Landing.tsx @@ -4,51 +4,29 @@ import { Bold } from '../components/typography/Bold.styled'; import { FlexColumn } from '../components/containers/FlexColumn.styled'; import { SafeArea } from '../layout/Layout.styled'; import ZupassButton from '../components/zupass-button'; +import Link from '../components/link'; function Landing() { return ( - We are a community of open-source researchers committed to solving the - hardest problems in decentralization, including the challenge of maintaining research and - academic independence in the wake of technological vertical integration and - hyper-financialization. Using plural mechanism design, we experiment with - novel ways to surface ideas in the public interest that transcend our biases — protocol, - politics, purse — while encouraging collaboration and insights across unlikely - intersections where breakthroughs tend to emerge. + This tool is designed to demonstrate Lexicon’s plural governance tooling. Users can + register, discuss, and vote on proposals, with vote results calculated quadratically or + plurally, with bridging bonuses calculated based on relationships between participants. - Our first convening was May 28 in Berlin, where the community was tasked to - allocate 100,000 ARB in research grants. - - - The funding mandate is MEV. We invite research proposals that explore MEV - narrowly and broadly — within and across execution layers (L1), rollups (L2s), oracles, - applications, etc. The mandate also extends to related topics such as chain abstraction, - account abstraction, gas fee optimization, AI agents, ZK, trusted hardware, and topics - related to decentralization — including richer notions of identity, contextual integrity - (“privacy”), collusion resistance, and partial common ownership. - - - This is a community event, where researchers set the agenda. Through a series - of structured interactions, the community will prioritize research and allocate funds, - relying on plural mechanisms —{' '} - - deliberation, plural voting, peer prediction, and healthy social recombination - {' '} - — to surface research in the broader public good. - - - The experiment will be novel, fun, and weird — like the best of research… and Berlin. - Surprise the community with your proposals! - - - Sign up with{' '} + If you’re here as part of a demo, please login with{' '} - Zupass here. + Zupass {' '} - Submissions received before May 15 will get more attention. + to continue. + + + If you’ve arrived here by other means, please check out our{' '} + GitHub or{' '} + click here to request a + demonstration. From 2963a25125f176d1d9bb5aec4106903a68b5d783 Mon Sep 17 00:00:00 2001 From: Camilo Vega <59750365+camilovegag@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:09:47 -0500 Subject: [PATCH 8/9] 687 add onboarding to develop (#694) * Install react joyride * Fix error and icon display * Add onboarding component * Add onboarding to event page * Add onboarding to results * Update store with onboarding changes * Add onboarding to results page * Add onboarding to cycles page --- package.json | 1 + .../src/components/onboarding/Onboarding.tsx | 73 ++++++ .../onboarding/Onboaring.styled.tsx | 9 + .../berlin/src/components/onboarding/index.ts | 1 + .../tables/results-table/ResultsTable.tsx | 9 +- packages/berlin/src/pages/Cycle.tsx | 217 ++++++++++++++---- packages/berlin/src/pages/Event.tsx | 104 ++++++--- packages/berlin/src/pages/Results.tsx | 134 +++++++++-- packages/berlin/src/store/index.ts | 26 ++- pnpm-lock.yaml | 132 +++++++++++ 10 files changed, 603 insertions(+), 103 deletions(-) create mode 100644 packages/berlin/src/components/onboarding/Onboarding.tsx create mode 100644 packages/berlin/src/components/onboarding/Onboaring.styled.tsx create mode 100644 packages/berlin/src/components/onboarding/index.ts diff --git a/package.json b/package.json index 7255ccf8..860d2d4b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.49.3", "react-hot-toast": "^2.4.1", + "react-joyride": "^2.8.2", "react-markdown": "^9.0.1", "react-router-dom": "^6.20.1", "styled-components": "^6.1.1", diff --git a/packages/berlin/src/components/onboarding/Onboarding.tsx b/packages/berlin/src/components/onboarding/Onboarding.tsx new file mode 100644 index 00000000..33c9c808 --- /dev/null +++ b/packages/berlin/src/components/onboarding/Onboarding.tsx @@ -0,0 +1,73 @@ +import { CSSProperties, ReactNode } from 'react'; +import Joyride, { CallBackProps } from 'react-joyride'; +import { useAppStore } from '../../store'; + +type OnboardingProps = { + type: 'event' | 'cycle' | 'results'; + steps: { + target: string; + content: ReactNode; + }[]; +}; + +const buttonBase: CSSProperties = { + fontFamily: 'var(--font-family-button)', + fontWeight: '500', + padding: '8px 16px', + textTransform: 'uppercase', +}; + +function Onboarding({ steps, type }: OnboardingProps) { + const { onboardingStatus, setOnboardingStatus } = useAppStore((state) => ({ + onboardingStatus: state.onboardingStatus, + setOnboardingStatus: state.setOnboardingStatus, + })); + + const run = onboardingStatus[type] !== 'COMPLETE'; + + const handleJoyrideCallback = (data: CallBackProps) => { + if (data.status === 'finished' || data.status === 'skipped') { + setOnboardingStatus(type, 'COMPLETE'); + console.log('Onboarding completed for', type); + } + }; + + return ( + + ); +} + +export default Onboarding; diff --git a/packages/berlin/src/components/onboarding/Onboaring.styled.tsx b/packages/berlin/src/components/onboarding/Onboaring.styled.tsx new file mode 100644 index 00000000..b7224a1b --- /dev/null +++ b/packages/berlin/src/components/onboarding/Onboaring.styled.tsx @@ -0,0 +1,9 @@ +import styled from 'styled-components'; +import { FlexColumn } from '../containers/FlexColumn.styled'; + +export const OnboardingCard = styled(FlexColumn)` + padding: 0rem; + background-color: var(--color-white); + text-align: left; + gap: 0.75rem; +`; diff --git a/packages/berlin/src/components/onboarding/index.ts b/packages/berlin/src/components/onboarding/index.ts new file mode 100644 index 00000000..c0ad2b14 --- /dev/null +++ b/packages/berlin/src/components/onboarding/index.ts @@ -0,0 +1 @@ +export { default } from './Onboarding'; diff --git a/packages/berlin/src/components/tables/results-table/ResultsTable.tsx b/packages/berlin/src/components/tables/results-table/ResultsTable.tsx index 2f21d4f2..3fa0b86b 100644 --- a/packages/berlin/src/components/tables/results-table/ResultsTable.tsx +++ b/packages/berlin/src/components/tables/results-table/ResultsTable.tsx @@ -18,6 +18,7 @@ import { FlexColumn } from '../../containers/FlexColumn.styled'; import { FlexRow } from '../../containers/FlexRow.styled'; import IconButton from '../../icon-button'; import Link from '../../link'; +import LucideIcon from '@/components/icon'; // Styled Components import { Card, Funding, Icon, Plurality, TitleContainer } from './ResultsTable.styled'; @@ -180,11 +181,9 @@ function ResultsTable({ $expanded, option, onClick, cycleId, eventId }: ResultsT Voter affiliations: {option.listOfGroupNames.join(', ')} - - - - - + + +
    ); diff --git a/packages/berlin/src/pages/Cycle.tsx b/packages/berlin/src/pages/Cycle.tsx index ecfc1666..8f53c856 100644 --- a/packages/berlin/src/pages/Cycle.tsx +++ b/packages/berlin/src/pages/Cycle.tsx @@ -34,6 +34,11 @@ import CycleColumns from '../components/columns/cycle-columns'; import OptionCard from '../components/option-card'; import { FINAL_QUESTION_TITLE, INITIAL_HEARTS } from '../utils/constants'; import { Heart } from 'lucide-react'; +import { OnboardingCard } from '@/components/onboarding/Onboaring.styled'; +import { Subtitle } from '@/components/typography/Subtitle.styled'; +import IconButton from '@/components/icon-button'; +import Onboarding from '../components/onboarding'; +import Icon from '@/components/icon'; type Order = 'asc' | 'desc'; type LocalUserVotes = { optionId: string; numOfVotes: number }[]; @@ -60,6 +65,7 @@ function Cycle() { const availableHearts = useAppStore((state) => state.availableHearts[cycle?.forumQuestions[0].id || '']) ?? INITIAL_HEARTS; + const theme = useAppStore((state) => state.theme); const setAvailableHearts = useAppStore((state) => state.setAvailableHearts); const [startAt, setStartAt] = useState(null); const [endAt, setEndAt] = useState(null); @@ -292,49 +298,178 @@ function Cycle() { ); }; - return ( - - - - {currentCycle?.questionTitle} - {voteInfo} - - You have {availableHearts} hearts left to give away: - - - {Array.from({ length: INITIAL_HEARTS }).map((_, id) => ( - - ))} - - - - {currentCycle?.questionOptions.length ? ( - - - {sortedOptions.options.map((option) => { - const userVote = localUserVotes.find((vote) => vote.optionId === option.id); - const numOfVotes = userVote ? userVote.numOfVotes : 0; - return ( - handleVoteWrapper(option.id)} - onUnVote={() => handleUnVoteWrapper(option.id)} + const steps = [ + { + target: '.step-1', + content: ( + + Voting Page + View vote items and allocate your hearts. + + ), + placement: 'center', + }, + { + target: '.step-2', + content: ( + + Vote + + + - ); - })} + + + Upvote or downvote a vote item. + + + ), + placement: 'center', + }, + { + target: '.step-3', + content: ( + + Save Your Votes + + You must click the + {' '} + button or your vote will not be recorded. + + + ), + placement: 'center', + }, + { + target: '.step-4', + content: ( + + Information + View vote item. + + + + + Current number of hearts allocated to this vote item. + + + ), + placement: 'center', + }, + { + target: '.step-5', + content: ( + + Voting Mechanisms + + + + Plurality score, unlike quadratic score, considers pre-existing participant + relationships + + + + ), + placement: 'center', + }, + { + target: '.step-6', + content: ( + + Expand a vote item + + + Click to view the vote item description and other useful information. + + {/* + + + Click to view the comments page and start a discussion with other participants. + + */} + + ), + placement: 'center', + }, + ]; + + return ( + <> + + + + + {currentCycle?.questionTitle} + {voteInfo} + + You have {availableHearts} hearts left to give away: + + + {Array.from({ length: INITIAL_HEARTS }).map((_, id) => ( + + ))} + + - ) : ( - - No options to show... - - )} - + {currentCycle?.questionOptions.length ? ( + + + {sortedOptions.options.map((option) => { + const userVote = localUserVotes.find((vote) => vote.optionId === option.id); + const numOfVotes = userVote ? userVote.numOfVotes : 0; + return ( + handleVoteWrapper(option.id)} + onUnVote={() => handleUnVoteWrapper(option.id)} + /> + ); + })} + + ) : ( + + No options to show... + + )} + + ); } diff --git a/packages/berlin/src/pages/Event.tsx b/packages/berlin/src/pages/Event.tsx index 1930710e..7add90e4 100644 --- a/packages/berlin/src/pages/Event.tsx +++ b/packages/berlin/src/pages/Event.tsx @@ -13,6 +13,49 @@ import { Table } from '../components/table'; import Button from '../components/button'; import EventCard from '../components/event-card'; import Link from '../components/link'; +import { OnboardingCard } from '@/components/onboarding/Onboaring.styled'; +import { Subtitle } from '@/components/typography/Subtitle.styled'; +import Onboarding from '@/components/onboarding'; + +const steps = [ + { + target: '.step-1', + content: ( + + Welcome + Welcome to our tool! + Would you like to take a tour to see how it works? + + ), + placement: 'center', + }, + { + target: '.step-2', + content: ( + + Open Votes + Explore current vote items, the vote deadline, and cast your vote. + + ), + placement: 'center', + }, + { + target: '.step-3', + content: ( + + Closed Votes + + Review past votes and see results by clicking the + {' '} + button. + + + ), + placement: 'center', + }, +]; function Event() { const navigate = useNavigate(); @@ -50,35 +93,38 @@ function Event() { }; return ( - - {/* */} - {!!openCycles?.length && } - {!!closedCycles?.length && } - {event && } - - Click to revisit the{' '} - - event rules - - ,{' '} - - trust assumptions - - , and the community’s{' '} - - data policy - - . - - + <> + + + {/* */} + {!!openCycles?.length && } + {!!closedCycles?.length && } + {event && } + + Click to revisit the{' '} + + event rules + + ,{' '} + + trust assumptions + + , and the community’s{' '} + + data policy + + . + + + ); } diff --git a/packages/berlin/src/pages/Results.tsx b/packages/berlin/src/pages/Results.tsx index 3faa5245..fde92c2c 100644 --- a/packages/berlin/src/pages/Results.tsx +++ b/packages/berlin/src/pages/Results.tsx @@ -11,9 +11,18 @@ import StatsTable from '../components/tables/stats-table'; import StatsColumns from '../components/columns/stats-columns'; import { FINAL_QUESTION_TITLE } from '../utils/constants'; import { Column } from '../components/tables/results-table/ResultsTable.styled'; +import { OnboardingCard } from '@/components/onboarding/Onboaring.styled'; +import { Body } from '@/components/typography/Body.styled'; +import IconButton from '@/components/icon-button'; +import { FlexRow } from '@/components/containers/FlexRow.styled'; +import { useAppStore } from '@/store'; +import Onboarding from '@/components/onboarding'; +import Icon from '@/components/icon'; +import { Heart, Radical } from 'lucide-react'; function Results() { const [expandedIndex, setExpandedIndex] = useState(null); + const theme = useAppStore((state) => state.theme); const { eventId, cycleId } = useParams(); @@ -60,6 +69,82 @@ function Results() { }, ]; + const steps = [ + { + target: '.step-1', + content: ( + + Results Page + See community decisions. + + ), + placement: 'center', + }, + { + target: '.step-2', + content: ( + + Icons + + + + + Quadratic score + + + + + + Hearts received by a vote item + + + + Plurality score + + + ), + placement: 'center', + }, + { + target: '.step-3', + content: ( + + Expand a vote item + + + + Clicking this icon will display the vote item description and other useful + information. + + + {/* + + Access the comments page to start a discussion with other participants. + */} + + ), + placement: 'center', + }, + ]; + const optionStatsArray = Object.entries(statistics?.optionStats || {}) .map(([id, stats]) => ({ id, @@ -70,30 +155,33 @@ function Results() { .sort((a, b) => parseFloat(b.pluralityScore) - parseFloat(a.pluralityScore)); return ( - - - Results for: {cycle?.forumQuestions?.[0].questionTitle} - - - {optionStatsArray.map((option, index) => ( - setExpandedIndex(expandedIndex === index ? null : index)} - /> - ))} - - Overall Statistics - - - {overallStatistics.map((stat) => ( - - ))} + <> + + + + Results for: {cycle?.forumQuestions?.[0].questionTitle} + + + {optionStatsArray.map((option, index) => ( + setExpandedIndex(expandedIndex === index ? null : index)} + /> + ))} + + Overall Statistics + + + {overallStatistics.map((stat) => ( + + ))} + - + ); } diff --git a/packages/berlin/src/store/index.ts b/packages/berlin/src/store/index.ts index 8b29e801..39d526d1 100644 --- a/packages/berlin/src/store/index.ts +++ b/packages/berlin/src/store/index.ts @@ -4,15 +4,22 @@ import { devtools, persist } from 'zustand/middleware'; type COMPLETION_STATUS = 'COMPLETE' | 'INCOMPLETE'; interface AppState { - onboardingStatus: COMPLETION_STATUS; userStatus: COMPLETION_STATUS; theme: 'light' | 'dark'; availableHearts: { [questionId: string]: number; }; + onboardingStatus: { + event: COMPLETION_STATUS; + cycle: COMPLETION_STATUS; + results: COMPLETION_STATUS; + }; setUserStatus: (status: COMPLETION_STATUS) => void; - setOnboardingStatus: (status: COMPLETION_STATUS) => void; setAvailableHearts: ({ hearts, questionId }: { questionId: string; hearts: number }) => void; + setOnboardingStatus: ( + type: keyof AppState['onboardingStatus'], + status: COMPLETION_STATUS, + ) => void; toggleTheme: () => void; reset: () => void; } @@ -21,13 +28,22 @@ export const useAppStore = create()( devtools( persist( (set) => ({ - onboardingStatus: 'INCOMPLETE', userStatus: 'INCOMPLETE', + onboardingStatus: { + event: 'INCOMPLETE', + cycle: 'INCOMPLETE', + results: 'INCOMPLETE', + }, theme: 'dark', // Default theme is dark availableHearts: {}, // Set the initial hearts value setUserStatus: (status: COMPLETION_STATUS) => set(() => ({ userStatus: status })), - setOnboardingStatus: (status: COMPLETION_STATUS) => - set(() => ({ onboardingStatus: status })), + setOnboardingStatus: (type, status) => + set((state) => ({ + onboardingStatus: { + ...state.onboardingStatus, + [type]: status, + }, + })), setAvailableHearts: ({ hearts, questionId }) => set((state) => ({ availableHearts: { ...state.availableHearts, [questionId]: hearts } })), toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cccfb5e..ae345bac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: react-hot-toast: specifier: ^2.4.1 version: 2.4.1(csstype@3.1.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-joyride: + specifier: ^2.8.2 + version: 2.8.2(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react-markdown: specifier: ^9.0.1 version: 9.0.1(@types/react@18.2.42)(react@18.2.0) @@ -899,6 +902,12 @@ packages: '@floating-ui/utils@0.2.1': resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + '@gilbarbara/deep-equal@0.1.2': + resolution: {integrity: sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA==} + + '@gilbarbara/deep-equal@0.3.1': + resolution: {integrity: sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==} + '@hookform/devtools@4.3.1': resolution: {integrity: sha512-CrWxEoHQZaOXJZVQ8KBgOuAa8p2LI8M0DAN5GTRTmdCieRwFVjVDEmuTAVazWVRRkpEQSgSt3KYp7VmmqXdEnw==} peerDependencies: @@ -2306,6 +2315,9 @@ packages: decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + deep-diff@1.0.2: + resolution: {integrity: sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==} + deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} @@ -2313,6 +2325,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} @@ -2769,6 +2785,12 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-lite@0.8.2: + resolution: {integrity: sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw==} + + is-lite@1.2.1: + resolution: {integrity: sha512-pgF+L5bxC+10hLBgf6R2P4ZZUBOQIIacbdo8YvuCP8/JvsWxG7aZ9p10DYuLtifFci4l3VITphhMlMV4Y+urPw==} + is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} @@ -3226,6 +3248,10 @@ packages: resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} engines: {node: '>=10'} + popper.js@1.16.1: + resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==} + deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 + postcss-cli@11.0.0: resolution: {integrity: sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==} engines: {node: '>=18'} @@ -3309,6 +3335,9 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -3353,6 +3382,12 @@ packages: peerDependencies: react: ^18.2.0 + react-floater@0.7.9: + resolution: {integrity: sha512-NXqyp9o8FAXOATOEo0ZpyaQ2KPb4cmPMXGWkx377QtJkIXHlHRAGer7ai0r0C1kG5gf+KJ6Gy+gdNIiosvSicg==} + peerDependencies: + react: 15 - 18 + react-dom: 15 - 18 + react-hook-form@7.49.3: resolution: {integrity: sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==} engines: {node: '>=18', pnpm: '8'} @@ -3366,9 +3401,21 @@ packages: react: '>=16' react-dom: '>=16' + react-innertext@1.1.5: + resolution: {integrity: sha512-PWAqdqhxhHIv80dT9znP2KvS+hfkbRovFp4zFYHFFlOoQLRiawIic81gKb3U1wEyJZgMwgs3JoLtwryASRWP3Q==} + peerDependencies: + '@types/react': '>=0.0.0 <=99' + react: '>=0.0.0 <=99' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-joyride@2.8.2: + resolution: {integrity: sha512-2QY8HB1G0I2OT0PKMUz7gg2HAjdkG2Bqi13r0Bb1V16PAwfb9khn4wWBTOJsGsjulbAWiQ3/0YrgNUHGFmuifw==} + peerDependencies: + react: 15 - 18 + react-dom: 15 - 18 + react-markdown@9.0.1: resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==} peerDependencies: @@ -3500,6 +3547,12 @@ packages: scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + scroll@3.0.1: + resolution: {integrity: sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==} + + scrollparent@2.1.0: + resolution: {integrity: sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA==} + scrypt-js@3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} @@ -3690,6 +3743,12 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tree-changes@0.11.2: + resolution: {integrity: sha512-4gXlUthrl+RabZw6lLvcCDl6KfJOCmrC16BC5CRdut1EAH509Omgg0BfKLY+ViRlzrvYOTWR0FMS2SQTwzumrw==} + + tree-changes@0.9.3: + resolution: {integrity: sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -3732,6 +3791,10 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} + type-fest@4.23.0: + resolution: {integrity: sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==} + engines: {node: '>=16'} + typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} @@ -4730,6 +4793,10 @@ snapshots: '@floating-ui/utils@0.2.1': {} + '@gilbarbara/deep-equal@0.1.2': {} + + '@gilbarbara/deep-equal@0.3.1': {} + '@hookform/devtools@4.3.1(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@emotion/react': 11.11.3(@types/react@18.2.42)(react@18.2.0) @@ -6921,12 +6988,16 @@ snapshots: dependencies: character-entities: 2.0.2 + deep-diff@1.0.2: {} + deep-eql@4.1.3: dependencies: type-detect: 4.0.8 deep-is@0.1.4: {} + deepmerge@4.3.1: {} + define-data-property@1.1.1: dependencies: get-intrinsic: 1.2.2 @@ -7542,6 +7613,10 @@ snapshots: is-hexadecimal@2.0.1: {} + is-lite@0.8.2: {} + + is-lite@1.2.1: {} + is-nan@1.3.2: dependencies: call-bind: 1.0.5 @@ -8120,6 +8195,8 @@ snapshots: dependencies: find-up: 5.0.0 + popper.js@1.16.1: {} + postcss-cli@11.0.0(jiti@1.21.0)(postcss@8.4.38): dependencies: chokidar: 3.6.0 @@ -8197,6 +8274,12 @@ snapshots: process@0.11.10: {} + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + property-information@6.5.0: {} public-encrypt@4.0.3: @@ -8241,6 +8324,16 @@ snapshots: react: 18.2.0 scheduler: 0.23.0 + react-floater@0.7.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + deepmerge: 4.3.1 + is-lite: 0.8.2 + popper.js: 1.16.1 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tree-changes: 0.9.3 + react-hook-form@7.49.3(react@18.2.0): dependencies: react: 18.2.0 @@ -8253,8 +8346,31 @@ snapshots: transitivePeerDependencies: - csstype + react-innertext@1.1.5(@types/react@18.2.42)(react@18.2.0): + dependencies: + '@types/react': 18.2.42 + react: 18.2.0 + react-is@16.13.1: {} + react-joyride@2.8.2(@types/react@18.2.42)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@gilbarbara/deep-equal': 0.3.1 + deep-diff: 1.0.2 + deepmerge: 4.3.1 + is-lite: 1.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-floater: 0.7.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-innertext: 1.1.5(@types/react@18.2.42)(react@18.2.0) + react-is: 16.13.1 + scroll: 3.0.1 + scrollparent: 2.1.0 + tree-changes: 0.11.2 + type-fest: 4.23.0 + transitivePeerDependencies: + - '@types/react' + react-markdown@9.0.1(@types/react@18.2.42)(react@18.2.0): dependencies: '@types/hast': 3.0.4 @@ -8486,6 +8602,10 @@ snapshots: dependencies: loose-envify: 1.4.0 + scroll@3.0.1: {} + + scrollparent@2.1.0: {} + scrypt-js@3.0.1: {} semver@6.3.1: {} @@ -8706,6 +8826,16 @@ snapshots: dependencies: is-number: 7.0.0 + tree-changes@0.11.2: + dependencies: + '@gilbarbara/deep-equal': 0.3.1 + is-lite: 1.2.1 + + tree-changes@0.9.3: + dependencies: + '@gilbarbara/deep-equal': 0.1.2 + is-lite: 0.8.2 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -8739,6 +8869,8 @@ snapshots: type-fest@0.20.2: {} + type-fest@4.23.0: {} + typescript@4.9.5: {} typescript@5.3.3: {} From 948fabde12740a9e0c2fa5b3fa9f6bf89fc56732 Mon Sep 17 00:00:00 2001 From: Camilo Vega <59750365+camilovegag@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:47:03 -0500 Subject: [PATCH 9/9] Remove old onboarding code (#695) * Delete page * Remove old onboarding code from app.tsx --- packages/berlin/src/App.tsx | 11 --- packages/berlin/src/pages/Onboarding.tsx | 102 ----------------------- 2 files changed, 113 deletions(-) delete mode 100644 packages/berlin/src/pages/Onboarding.tsx diff --git a/packages/berlin/src/App.tsx b/packages/berlin/src/App.tsx index a7a349db..b517473d 100644 --- a/packages/berlin/src/App.tsx +++ b/packages/berlin/src/App.tsx @@ -18,7 +18,6 @@ import Event from './pages/Event.tsx'; import Events from './pages/Events.tsx'; import Holding from './pages/Holding'; import Landing from './pages/Landing'; -import Onboarding from './pages/Onboarding'; import PassportPopupRedirect from './pages/Popup'; import PublicGroupRegistration from './pages/PublicGroupRegistration.tsx'; import Register from './pages/Register'; @@ -72,12 +71,6 @@ async function redirectOnLandingLoader(queryClient: QueryClient) { return null; } - const onboardingState = useAppStore.getState().onboardingStatus; - - if (onboardingState === 'INCOMPLETE') { - return redirect('/onboarding'); - } - const events = await queryClient.fetchQuery({ queryKey: ['events'], queryFn: fetchEvents, @@ -195,10 +188,6 @@ const router = (queryClient: QueryClient) => { loader: () => redirectToLandingLoader(queryClient), children: [ - { - path: '/onboarding', - Component: Onboarding, - }, { path: '/data-policy', Component: DataPolicy, diff --git a/packages/berlin/src/pages/Onboarding.tsx b/packages/berlin/src/pages/Onboarding.tsx deleted file mode 100644 index beb4f67e..00000000 --- a/packages/berlin/src/pages/Onboarding.tsx +++ /dev/null @@ -1,102 +0,0 @@ -// React and third-party libraries -import { useEffect, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; - -// Components -import { Body } from '../components/typography/Body.styled'; -import { Bold } from '../components/typography/Bold.styled'; -import { FlexColumn } from '../components/containers/FlexColumn.styled'; -import { FlexRow } from '../components/containers/FlexRow.styled'; -import { SafeArea } from '../layout/Layout.styled'; -import { Subtitle } from '../components/typography/Subtitle.styled'; -import Button from '../components/button'; -import Dots from '../components/dots'; - -// Data -import onboarding from '../data/onboarding'; -import { useAppStore } from '../store'; -const { data } = onboarding; - -function Onboarding() { - const navigate = useNavigate(); - const location = useLocation(); - const [previousPath, setPreviousPath] = useState(null); - const setOnboardingStatus = useAppStore((state) => state.setOnboardingStatus); - const [step, setStep] = useState(0); - - useEffect(() => { - if (location && location.state) { - setPreviousPath(location.state.previousPath); - if (location.state.onboardingStep) { - setStep(location.state.onboardingStep); - } - } - }, [location]); - - const handleSkip = () => { - if (previousPath) { - navigate(previousPath); - } else { - navigate('/account'); - setOnboardingStatus('COMPLETE'); - } - }; - - const handleNext = () => { - if (step < data.length - 1) { - setStep((prevStep) => prevStep + 1); - return; - } - - handleSkip(); - }; - - return ( - - - {data[step].title} - - setStep(i)} /> - - - - - - - ); -} - -export default Onboarding; - -type BodyContentProps = { - content: string | { id: number; title?: string; text: string }[]; -}; - -function BodyContent({ content }: BodyContentProps) { - if (Array.isArray(content) && content[0].title) { - return ( - - {content.map((item) => ( - - {item.title} - {item.text} - - ))} - - ); - } - - if (Array.isArray(content)) { - return ( - - {content.map((item) => ( - {item.text} - ))} - - ); - } - - return {content}; -}