diff --git a/.claude/claude_project.json b/.claude/claude_project.json new file mode 100644 index 0000000..198c32b --- /dev/null +++ b/.claude/claude_project.json @@ -0,0 +1,66 @@ +{ + "mcpServers": { + "serena": { + "type": "stdio", + "command": "uvx", + "args": [ + "--from", + "git+https://github.com/oraios/serena", + "serena", + "start-mcp-server", + "--context", + "ide-assistant", + "--project", + "${workspaceFolder}" + ], + "env": {} + }, + "zen": { + "type": "stdio", + "command": "pwsh", + "args": [ + "-NoLogo", + "-NoProfile", + "-Command", + "$p=(Get-Command uvx -ErrorAction SilentlyContinue).Source; if(-not $p){$c=@(\"$HOME\\.local\\bin\\uvx.exe\",\"C:\\\\Program Files\\\\uv\\\\bin\\\\uvx.exe\"); foreach($i in $c){ if(Test-Path $i){$p=$i; break}}}; if($p){ & $p --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server } else { Write-Error 'uvx not found'; exit 1 }" + ], + "env": { + "GEMINI_API_KEY": "your_gemini_key", + "OPENAI_API_KEY": "your_openai_key" + } + }, + "playwright": { + "type": "stdio", + "command": "cmd", + "args": [ + "/c", + "npx", + "-y", + "@playwright/mcp@latest" + ], + "env": {} + }, + "context7": { + "type": "stdio", + "command": "npx", + "args": [ + "-y", + "@upstash/context7-mcp@latest" + ], + "env": {} + }, + "@21st-dev/magic": { + "type": "stdio", + "command": "cmd", + "args": [ + "/c", + "npx", + "-y", + "@21st-dev/magic@latest" + ], + "env": { + "API_KEY": "adb246737aabae0b2f124fc85dc03737a0f65d9660b786732c31578649da10e5" + } + } + }, +} \ No newline at end of file diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..6ca5127 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,27 @@ +{ + "permissions": { + "allow": [ + "Bash(mkdir:*)", + "Read(C:\\Users\\mpcia/**)", + "Read(C:\\Users\\mpcia/**)", + "mcp__serena__activate_project", + "mcp__serena__list_dir", + "mcp__playwright__browser_navigate", + "mcp__playwright__browser_take_screenshot", + "mcp__playwright__browser_snapshot", + "mcp__playwright__browser_type", + "mcp__playwright__browser_click", + "mcp__playwright__browser_press_key", + "mcp__playwright__browser_wait_for", + "mcp__serena__find_symbol", + "mcp__serena__search_for_pattern", + "mcp___21st-dev_magic__21st_magic_component_inspiration", + "mcp__context7__resolve-library-id", + "mcp__context7__get-library-docs", + "Bash(npm install:*)", + "Bash(git add:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/.playwright-mcp/dashboard-admin.png b/.playwright-mcp/dashboard-admin.png new file mode 100644 index 0000000..a577de1 Binary files /dev/null and b/.playwright-mcp/dashboard-admin.png differ diff --git a/.playwright-mcp/dashboard-events.png b/.playwright-mcp/dashboard-events.png new file mode 100644 index 0000000..fece509 Binary files /dev/null and b/.playwright-mcp/dashboard-events.png differ diff --git a/.playwright-mcp/dashboard-main.png b/.playwright-mcp/dashboard-main.png new file mode 100644 index 0000000..34191c0 Binary files /dev/null and b/.playwright-mcp/dashboard-main.png differ diff --git a/.playwright-mcp/dashboard-member-list.png b/.playwright-mcp/dashboard-member-list.png new file mode 100644 index 0000000..afd0cba Binary files /dev/null and b/.playwright-mcp/dashboard-member-list.png differ diff --git a/.playwright-mcp/dashboard-profile.png b/.playwright-mcp/dashboard-profile.png new file mode 100644 index 0000000..27fa046 Binary files /dev/null and b/.playwright-mcp/dashboard-profile.png differ diff --git a/.playwright-mcp/landing-page.png b/.playwright-mcp/landing-page.png new file mode 100644 index 0000000..d9edb0e Binary files /dev/null and b/.playwright-mcp/landing-page.png differ diff --git a/.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl b/.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl new file mode 100644 index 0000000..a62d947 Binary files /dev/null and b/.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl differ diff --git a/.serena/project.yml b/.serena/project.yml new file mode 100644 index 0000000..c6ec35a --- /dev/null +++ b/.serena/project.yml @@ -0,0 +1,68 @@ +# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby) +# * For C, use cpp +# * For JavaScript, use typescript +# Special requirements: +# * csharp: Requires the presence of a .sln file in the project folder. +language: typescript + +# whether to use the project's gitignore file to ignore files +# Added on 2025-04-07 +ignore_all_files_in_gitignore: true +# list of additional paths to ignore +# same syntax as gitignore, so you can use * and ** +# Was previously called `ignored_dirs`, please update your config if you are using that. +# Added (renamed) on 2025-04-07 +ignored_paths: [] + +# whether the project is in read-only mode +# If set to true, all editing tools will be disabled and attempts to use them will result in an error +# Added on 2025-04-18 +read_only: false + + +# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. +# Below is the complete list of tools for convenience. +# To make sure you have the latest list of tools, and to view their descriptions, +# execute `uv run scripts/print_tool_overview.py`. +# +# * `activate_project`: Activates a project by name. +# * `check_onboarding_performed`: Checks whether project onboarding was already performed. +# * `create_text_file`: Creates/overwrites a file in the project directory. +# * `delete_lines`: Deletes a range of lines within a file. +# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `execute_shell_command`: Executes a shell command. +# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. +# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). +# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. +# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. +# * `initial_instructions`: Gets the initial instructions for the current project. +# Should only be used in settings where the system prompt cannot be set, +# e.g. in clients you have no control over, like Claude Desktop. +# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. +# * `insert_at_line`: Inserts content at a given line in a file. +# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. +# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). +# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). +# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). +# * `read_file`: Reads a file within the project directory. +# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. +# * `remove_project`: Removes a project from the Serena configuration. +# * `replace_lines`: Replaces a range of lines within a file with new content. +# * `replace_symbol_body`: Replaces the full definition of a symbol. +# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `search_for_pattern`: Performs a search for a pattern in the project. +# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. +# * `switch_modes`: Activates modes by providing a list of their names +# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. +# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. +# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. +# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +excluded_tools: [] + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +project_name: "monacousa-portal" diff --git a/Design/README.md b/Design/README.md new file mode 100644 index 0000000..479057b --- /dev/null +++ b/Design/README.md @@ -0,0 +1,480 @@ +# MonacoUSA Portal Design System Implementation Guide + +## 🎨 Overview + +This comprehensive guide outlines the complete visual redesign of the MonacoUSA Portal, transitioning from a standard Vuetify implementation to a premium, custom design system featuring Monaco's signature red and white color scheme with modern glass morphism effects. + +## 📋 Table of Contents + +1. [Design Philosophy](#design-philosophy) +2. [Technical Stack](#technical-stack) +3. [Migration Strategy](#migration-strategy) +4. [Component Architecture](#component-architecture) +5. [Implementation Roadmap](#implementation-roadmap) +6. [Performance Guidelines](#performance-guidelines) +7. [Accessibility Standards](#accessibility-standards) + +## Design Philosophy + +### Core Principles +- **Premium Feel**: Every interaction should feel smooth and sophisticated +- **Brand Identity**: Monaco's red (#dc2626) as the primary accent color +- **Modern Aesthetics**: Glass morphism, subtle animations, and floating elements +- **User Experience**: Intuitive navigation with clear visual hierarchy +- **Performance**: Animations that enhance, not hinder, user experience + +### Visual Language +- **Glass Morphism**: Semi-transparent surfaces with backdrop blur +- **Gradient Accents**: Dynamic gradients from Monaco red to deeper shades +- **Floating Elements**: Subtle shadows and depth for interactive components +- **Micro-animations**: Smooth transitions on hover, click, and state changes +- **Consistent Spacing**: 8px grid system for alignment and padding + +## Technical Stack + +### Current Setup +- **Framework**: Nuxt 3.8.2 +- **UI Library**: Vuetify 3.4.7 (to be replaced) +- **Icons**: Material Design Icons (transitioning to Lucide) +- **Authentication**: Keycloak integration +- **Styling**: SCSS with scoped components + +### New Additions +- **Animation Libraries**: + - VueUse Motion (preferred for Vue integration) + - GSAP (for complex animations) + - Anime.js (lightweight alternative) +- **Icons**: Lucide Icons (modern, customizable) +- **Utilities**: Tailwind CSS (for rapid prototyping) +- **State Management**: Pinia (already implemented) + +## Migration Strategy + +### Phase 1: Foundation (Week 1-2) +1. Set up new style architecture +2. Create base component library +3. Implement color system and typography +4. Set up animation utilities + +### Phase 2: Core Components (Week 3-4) +1. Replace navigation components +2. Implement custom dropdowns and selects +3. Create button variants +4. Build card components + +### Phase 3: Page Templates (Week 5-6) +1. Dashboard layouts +2. Data tables with glass effects +3. Form components +4. Modal and dialog systems + +### Phase 4: Polish & Optimization (Week 7-8) +1. Performance tuning +2. Accessibility audit +3. Cross-browser testing +4. Documentation completion + +## Component Architecture + +### File Structure +``` +components/ +├── ui/ # Base UI components +│ ├── MonacoButton.vue +│ ├── GlassCard.vue +│ ├── AnimatedDropdown.vue +│ └── FloatingInput.vue +├── layout/ # Layout components +│ ├── DashboardSidebar.vue +│ ├── AppHeader.vue +│ └── PageContainer.vue +├── features/ # Feature-specific components +│ ├── MemberCard.vue +│ ├── EventCalendar.vue +│ └── DuesTracker.vue +└── shared/ # Shared utilities + ├── LoadingSpinner.vue + ├── ErrorBoundary.vue + └── TransitionWrapper.vue +``` + +### Component Guidelines + +#### Naming Convention +- PascalCase for component files +- Prefix with "Monaco" for custom branded components +- Use descriptive names (e.g., `GlassDropdownMenu` not `Dropdown`) + +#### Props & Events +```vue + +``` + +#### Composition API Pattern +```vue + +``` + +## Implementation Roadmap + +### Week 1: Setup & Foundation +- [ ] Configure animation libraries +- [ ] Set up SCSS architecture +- [ ] Create color system utilities +- [ ] Implement base glass morphism styles +- [ ] Set up Lucide icons integration + +### Week 2: Core Components +- [ ] Custom dropdown components +- [ ] Button system with variants +- [ ] Card components with glass effects +- [ ] Form inputs with floating labels +- [ ] Navigation components + +### Week 3: Dashboard Implementation +- [ ] Member dashboard layout +- [ ] Board dashboard enhancements +- [ ] Admin panel structure +- [ ] Widget components +- [ ] Chart integrations + +### Week 4: Advanced Features +- [ ] Event calendar with animations +- [ ] Member management interface +- [ ] Dues payment flow +- [ ] Profile components +- [ ] Settings panels + +### Week 5: Responsive Design +- [ ] Mobile navigation +- [ ] Tablet optimizations +- [ ] Touch interactions +- [ ] Gesture support +- [ ] PWA enhancements + +### Week 6: Testing & Optimization +- [ ] Performance profiling +- [ ] Bundle optimization +- [ ] Lazy loading implementation +- [ ] Animation performance tuning +- [ ] Memory leak detection + +## Performance Guidelines + +### Animation Performance +```scss +// Use transform and opacity for animations +.animated-element { + will-change: transform, opacity; + transform: translateZ(0); // Enable hardware acceleration +} + +// Avoid animating expensive properties +// BAD: width, height, padding, margin +// GOOD: transform, opacity, filter +``` + +### Component Optimization +```vue + +
+ +
+ + + + + + +``` + +### Bundle Size Management +- Tree-shake unused Vuetify components +- Lazy load animation libraries +- Use dynamic imports for heavy features +- Implement code splitting by route +- Optimize images with next-gen formats + +## Accessibility Standards + +### WCAG 2.1 Compliance +- **Color Contrast**: Ensure 4.5:1 ratio for normal text +- **Focus Indicators**: Clear visual focus states +- **Keyboard Navigation**: Full keyboard support +- **Screen Readers**: Proper ARIA labels +- **Motion Sensitivity**: Respect prefers-reduced-motion + +### Implementation Examples +```vue + + + + + +``` + +## Style Guidelines + +### Color System +```scss +// Primary Colors +$monaco-red: #dc2626; +$monaco-red-dark: #b91c1c; +$monaco-red-light: #ef4444; +$monaco-white: #ffffff; + +// Gradients +$monaco-gradient: linear-gradient(135deg, $monaco-red 0%, $monaco-red-dark 100%); +$monaco-gradient-reverse: linear-gradient(135deg, $monaco-red-light 0%, $monaco-red 100%); + +// Glass Effects +$glass-bg: rgba(255, 255, 255, 0.7); +$glass-border: rgba(255, 255, 255, 0.3); +$glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +$glass-blur: 20px; +``` + +### Typography Scale +```scss +// Font Family +$font-primary: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; +$font-mono: 'Fira Code', 'Monaco', monospace; + +// Font Sizes +$text-xs: 0.75rem; // 12px +$text-sm: 0.875rem; // 14px +$text-base: 1rem; // 16px +$text-lg: 1.125rem; // 18px +$text-xl: 1.25rem; // 20px +$text-2xl: 1.5rem; // 24px +$text-3xl: 1.875rem; // 30px +$text-4xl: 2.25rem; // 36px +``` + +### Spacing System +```scss +// Based on 8px grid +$space-1: 0.25rem; // 4px +$space-2: 0.5rem; // 8px +$space-3: 0.75rem; // 12px +$space-4: 1rem; // 16px +$space-5: 1.25rem; // 20px +$space-6: 1.5rem; // 24px +$space-8: 2rem; // 32px +$space-10: 2.5rem; // 40px +$space-12: 3rem; // 48px +$space-16: 4rem; // 64px +``` + +## Component Examples + +### Glass Card Component +```vue + + + + + +``` + +## Testing Strategy + +### Unit Testing +```typescript +// components/__tests__/MonacoButton.spec.ts +import { mount } from '@vue/test-utils' +import MonacoButton from '~/components/ui/MonacoButton.vue' + +describe('MonacoButton', () => { + it('renders with correct variant class', () => { + const wrapper = mount(MonacoButton, { + props: { variant: 'gradient' } + }) + expect(wrapper.classes()).toContain('monaco-button--gradient') + }) + + it('emits click event', async () => { + const wrapper = mount(MonacoButton) + await wrapper.trigger('click') + expect(wrapper.emitted('click')).toHaveLength(1) + }) +}) +``` + +### E2E Testing +```typescript +// e2e/dashboard.spec.ts +import { test, expect } from '@playwright/test' + +test('dashboard loads with glass morphism effects', async ({ page }) => { + await page.goto('/dashboard') + + const glassCard = page.locator('.glass-card').first() + await expect(glassCard).toBeVisible() + + const styles = await glassCard.evaluate(el => + window.getComputedStyle(el) + ) + expect(styles.backdropFilter).toContain('blur') +}) +``` + +## Deployment Checklist + +### Pre-deployment +- [ ] Run full test suite +- [ ] Check bundle size (<500KB initial) +- [ ] Validate accessibility scores +- [ ] Test on all target browsers +- [ ] Optimize images and assets +- [ ] Review security headers + +### Performance Metrics +- First Contentful Paint: <1.5s +- Time to Interactive: <3s +- Cumulative Layout Shift: <0.1 +- First Input Delay: <100ms +- Lighthouse Score: >90 + +### Browser Support +- Chrome 90+ +- Firefox 88+ +- Safari 14+ +- Edge 90+ +- Mobile Safari 14+ +- Chrome Mobile 90+ + +## Resources + +### Documentation +- [Vue 3 Composition API](https://vuejs.org/guide/extras/composition-api-faq.html) +- [Nuxt 3 Documentation](https://nuxt.com/docs) +- [VueUse Motion](https://motion.vueuse.org/) +- [GSAP Documentation](https://greensock.com/docs/) +- [Lucide Icons](https://lucide.dev/) + +### Design Inspiration +- [Glass Morphism Examples](https://glassmorphism.com/) +- [Monaco Brand Guidelines](internal-link) +- [Material Design 3](https://m3.material.io/) + +### Tools +- [Contrast Checker](https://webaim.org/resources/contrastchecker/) +- [Bundle Analyzer](https://github.com/nuxt/devtools) +- [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci) + +## Support + +For questions or assistance with implementation: +- Technical Lead: [Contact Info] +- Design Team: [Contact Info] +- Documentation: This guide and `/Design` folder + +--- + +*Last Updated: December 2024* +*Version: 1.0.0* \ No newline at end of file diff --git a/Design/components/dropdowns/AnimatedSelect.vue b/Design/components/dropdowns/AnimatedSelect.vue new file mode 100644 index 0000000..34c3901 --- /dev/null +++ b/Design/components/dropdowns/AnimatedSelect.vue @@ -0,0 +1,510 @@ + + + + + \ No newline at end of file diff --git a/Design/components/dropdowns/GlassDropdown.vue b/Design/components/dropdowns/GlassDropdown.vue new file mode 100644 index 0000000..117f7fc --- /dev/null +++ b/Design/components/dropdowns/GlassDropdown.vue @@ -0,0 +1,713 @@ + + + + + \ No newline at end of file diff --git a/Design/components/dropdowns/MonacoDropdown.vue b/Design/components/dropdowns/MonacoDropdown.vue new file mode 100644 index 0000000..aaaef89 --- /dev/null +++ b/Design/components/dropdowns/MonacoDropdown.vue @@ -0,0 +1,391 @@ + + + + + \ No newline at end of file diff --git a/Design/design-system.md b/Design/design-system.md new file mode 100644 index 0000000..e12570f --- /dev/null +++ b/Design/design-system.md @@ -0,0 +1,753 @@ +# MonacoUSA Portal Design System + +## 🎨 Visual Identity + +### Brand Colors + +#### Primary Palette +```scss +// Monaco Red Spectrum +$monaco-red-50: #fef2f2; +$monaco-red-100: #fee2e2; +$monaco-red-200: #fecaca; +$monaco-red-300: #fca5a5; +$monaco-red-400: #f87171; +$monaco-red-500: #ef4444; +$monaco-red-600: #dc2626; // Primary Brand Color +$monaco-red-700: #b91c1c; +$monaco-red-800: #991b1b; +$monaco-red-900: #7f1d1d; + +// Neutral Palette +$gray-50: #fafafa; +$gray-100: #f4f4f5; +$gray-200: #e4e4e7; +$gray-300: #d4d4d8; +$gray-400: #a1a1aa; +$gray-500: #71717a; +$gray-600: #52525b; +$gray-700: #3f3f46; +$gray-800: #27272a; +$gray-900: #18181b; +``` + +#### Gradient Definitions +```scss +// Primary Gradients +$gradient-monaco: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); +$gradient-monaco-light: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); +$gradient-monaco-dark: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%); + +// Accent Gradients +$gradient-sunset: linear-gradient(135deg, #dc2626 0%, #f59e0b 100%); +$gradient-wine: linear-gradient(135deg, #991b1b 0%, #4c1d95 100%); +$gradient-royal: linear-gradient(135deg, #dc2626 0%, #1e40af 100%); + +// Glass Gradients +$gradient-glass-light: linear-gradient(135deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.4) 100%); +$gradient-glass-dark: linear-gradient(135deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.4) 100%); +``` + +### Typography + +#### Font Stack +```scss +// Primary Font Family +$font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + +// Monospace Font Family +$font-mono: 'Fira Code', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', monospace; + +// Display Font (for headers) +$font-display: 'Poppins', $font-sans; +``` + +#### Type Scale +```scss +// Font Sizes +$text-xs: 0.75rem; // 12px +$text-sm: 0.875rem; // 14px +$text-base: 1rem; // 16px +$text-lg: 1.125rem; // 18px +$text-xl: 1.25rem; // 20px +$text-2xl: 1.5rem; // 24px +$text-3xl: 1.875rem; // 30px +$text-4xl: 2.25rem; // 36px +$text-5xl: 3rem; // 48px +$text-6xl: 3.75rem; // 60px +$text-7xl: 4.5rem; // 72px + +// Line Heights +$leading-none: 1; +$leading-tight: 1.25; +$leading-snug: 1.375; +$leading-normal: 1.5; +$leading-relaxed: 1.625; +$leading-loose: 2; + +// Font Weights +$font-thin: 100; +$font-light: 300; +$font-normal: 400; +$font-medium: 500; +$font-semibold: 600; +$font-bold: 700; +$font-extrabold: 800; +$font-black: 900; +``` + +### Spacing System + +```scss +// Based on 4px grid +$space-0: 0; // 0px +$space-px: 1px; // 1px +$space-0_5: 0.125rem; // 2px +$space-1: 0.25rem; // 4px +$space-1_5: 0.375rem; // 6px +$space-2: 0.5rem; // 8px +$space-2_5: 0.625rem; // 10px +$space-3: 0.75rem; // 12px +$space-3_5: 0.875rem; // 14px +$space-4: 1rem; // 16px +$space-5: 1.25rem; // 20px +$space-6: 1.5rem; // 24px +$space-7: 1.75rem; // 28px +$space-8: 2rem; // 32px +$space-9: 2.25rem; // 36px +$space-10: 2.5rem; // 40px +$space-12: 3rem; // 48px +$space-14: 3.5rem; // 56px +$space-16: 4rem; // 64px +$space-20: 5rem; // 80px +$space-24: 6rem; // 96px +$space-28: 7rem; // 112px +$space-32: 8rem; // 128px +``` + +### Border Radius + +```scss +$radius-none: 0; +$radius-sm: 0.125rem; // 2px +$radius-base: 0.25rem; // 4px +$radius-md: 0.375rem; // 6px +$radius-lg: 0.5rem; // 8px +$radius-xl: 0.75rem; // 12px +$radius-2xl: 1rem; // 16px +$radius-3xl: 1.5rem; // 24px +$radius-full: 9999px; // Pill shape +``` + +### Shadows + +```scss +// Elevation Shadows +$shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +$shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); +$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); +$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); +$shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); +$shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); + +// Glass Shadows +$shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.1); +$shadow-glass-hover: 0 12px 40px rgba(0, 0, 0, 0.15); + +// Monaco Brand Shadows +$shadow-monaco: 0 10px 40px rgba(220, 38, 38, 0.15); +$shadow-monaco-intense: 0 20px 60px rgba(220, 38, 38, 0.25); +``` + +## 🎯 Component Patterns + +### Glass Morphism + +```scss +@mixin glass-effect($bg-opacity: 0.7, $blur: 20px) { + background: rgba(255, 255, 255, $bg-opacity); + backdrop-filter: blur($blur); + -webkit-backdrop-filter: blur($blur); + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: $shadow-glass; +} + +@mixin glass-dark($bg-opacity: 0.7, $blur: 20px) { + background: rgba(0, 0, 0, $bg-opacity); + backdrop-filter: blur($blur); + -webkit-backdrop-filter: blur($blur); + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: $shadow-glass; +} + +@mixin glass-colored($color: $monaco-red-600, $opacity: 0.1, $blur: 20px) { + background: rgba($color, $opacity); + backdrop-filter: blur($blur); + -webkit-backdrop-filter: blur($blur); + border: 1px solid rgba($color, 0.2); + box-shadow: 0 8px 32px rgba($color, 0.1); +} +``` + +### Animation Patterns + +```scss +// Timing Functions +$ease-in-out-smooth: cubic-bezier(0.4, 0, 0.2, 1); +$ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1); +$ease-in-out-elastic: cubic-bezier(0.68, -0.55, 0.265, 1.55); + +// Duration Scale +$duration-instant: 0ms; +$duration-fast: 150ms; +$duration-base: 300ms; +$duration-slow: 500ms; +$duration-slower: 700ms; +$duration-slowest: 1000ms; + +// Animation Mixins +@mixin hover-lift($distance: -2px, $duration: $duration-base) { + transition: transform $duration $ease-in-out-smooth; + + &:hover { + transform: translateY($distance); + } +} + +@mixin hover-scale($scale: 1.05, $duration: $duration-base) { + transition: transform $duration $ease-in-out-smooth; + + &:hover { + transform: scale($scale); + } +} + +@mixin pulse-animation($scale: 1.05, $duration: 2s) { + animation: pulse $duration infinite; + + @keyframes pulse { + 0%, 100% { + transform: scale(1); + opacity: 1; + } + 50% { + transform: scale($scale); + opacity: 0.8; + } + } +} + +@mixin float-animation($distance: 10px, $duration: 3s) { + animation: float $duration ease-in-out infinite; + + @keyframes float { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-$distance); + } + } +} +``` + +### Button Variants + +```scss +// Base Button +@mixin button-base { + display: inline-flex; + align-items: center; + justify-content: center; + padding: $space-2_5 $space-5; + font-weight: $font-medium; + font-size: $text-sm; + line-height: $leading-tight; + border-radius: $radius-xl; + transition: all $duration-base $ease-in-out-smooth; + cursor: pointer; + user-select: none; + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } +} + +// Primary Button +@mixin button-primary { + @include button-base; + background: $gradient-monaco; + color: white; + border: none; + box-shadow: $shadow-md; + + &:hover:not(:disabled) { + box-shadow: $shadow-monaco; + transform: translateY(-1px); + } + + &:active:not(:disabled) { + transform: translateY(0); + } +} + +// Glass Button +@mixin button-glass { + @include button-base; + @include glass-effect(0.8, 10px); + color: $monaco-red-600; + + &:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.9); + box-shadow: $shadow-glass-hover; + transform: translateY(-1px); + } +} + +// Ghost Button +@mixin button-ghost { + @include button-base; + background: transparent; + color: $monaco-red-600; + border: 2px solid $monaco-red-600; + + &:hover:not(:disabled) { + background: rgba($monaco-red-600, 0.1); + border-color: $monaco-red-700; + } +} +``` + +### Card Patterns + +```scss +// Base Card +@mixin card-base { + border-radius: $radius-2xl; + padding: $space-6; + transition: all $duration-base $ease-in-out-smooth; +} + +// Glass Card +@mixin card-glass { + @include card-base; + @include glass-effect; + + &:hover { + @include hover-lift(-4px); + box-shadow: $shadow-glass-hover; + } +} + +// Gradient Card +@mixin card-gradient { + @include card-base; + background: $gradient-monaco; + color: white; + box-shadow: $shadow-monaco; + + &:hover { + @include hover-lift(-4px); + box-shadow: $shadow-monaco-intense; + } +} + +// Floating Card +@mixin card-floating { + @include card-base; + background: white; + box-shadow: $shadow-lg; + @include float-animation(5px, 4s); + + &:hover { + animation-play-state: paused; + box-shadow: $shadow-xl; + } +} +``` + +### Form Elements + +```scss +// Input Base +@mixin input-base { + width: 100%; + padding: $space-3 $space-4; + font-size: $text-base; + border-radius: $radius-xl; + transition: all $duration-base $ease-in-out-smooth; + + &:focus { + outline: none; + } + + &::placeholder { + color: $gray-400; + } +} + +// Glass Input +@mixin input-glass { + @include input-base; + @include glass-effect(0.6, 10px); + border: 2px solid transparent; + + &:focus { + border-color: $monaco-red-600; + background: rgba(255, 255, 255, 0.8); + box-shadow: 0 0 0 3px rgba($monaco-red-600, 0.1); + } +} + +// Floating Label +@mixin floating-label { + position: relative; + + label { + position: absolute; + left: $space-4; + top: 50%; + transform: translateY(-50%); + transition: all $duration-base $ease-in-out-smooth; + pointer-events: none; + color: $gray-500; + font-size: $text-base; + } + + input:focus + label, + input:not(:placeholder-shown) + label { + top: 0; + transform: translateY(-50%) scale(0.8); + background: white; + padding: 0 $space-2; + color: $monaco-red-600; + } +} +``` + +## 🎭 Animation Library + +### Entrance Animations + +```scss +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes slide-up { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.9); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes rotate-in { + from { + opacity: 0; + transform: rotate(-10deg) scale(0.9); + } + to { + opacity: 1; + transform: rotate(0) scale(1); + } +} +``` + +### Interaction Animations + +```scss +@keyframes bounce { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} + +@keyframes shake { + 0%, 100% { + transform: translateX(0); + } + 25% { + transform: translateX(-5px); + } + 75% { + transform: translateX(5px); + } +} + +@keyframes wiggle { + 0%, 100% { + transform: rotate(0deg); + } + 25% { + transform: rotate(-3deg); + } + 75% { + transform: rotate(3deg); + } +} +``` + +### Loading Animations + +```scss +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@keyframes pulse-ring { + 0% { + transform: scale(0.5); + opacity: 1; + } + 80%, 100% { + transform: scale(1.5); + opacity: 0; + } +} + +@keyframes shimmer { + 0% { + background-position: -200% 0; + } + 100% { + background-position: 200% 0; + } +} + +.shimmer-effect { + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + rgba(255, 255, 255, 0.3) 50%, + rgba(255, 255, 255, 0) 100% + ); + background-size: 200% 100%; + animation: shimmer 1.5s infinite; +} +``` + +## 📱 Responsive Design + +### Breakpoints + +```scss +// Mobile First Breakpoints +$screen-sm: 640px; // Small devices +$screen-md: 768px; // Medium devices +$screen-lg: 1024px; // Large devices +$screen-xl: 1280px; // Extra large devices +$screen-2xl: 1536px; // 2X Extra large devices + +// Mixins +@mixin sm { + @media (min-width: $screen-sm) { + @content; + } +} + +@mixin md { + @media (min-width: $screen-md) { + @content; + } +} + +@mixin lg { + @media (min-width: $screen-lg) { + @content; + } +} + +@mixin xl { + @media (min-width: $screen-xl) { + @content; + } +} + +@mixin 2xl { + @media (min-width: $screen-2xl) { + @content; + } +} +``` + +### Container Widths + +```scss +.container { + width: 100%; + margin-left: auto; + margin-right: auto; + padding-left: $space-4; + padding-right: $space-4; + + @include sm { + max-width: $screen-sm; + } + + @include md { + max-width: $screen-md; + } + + @include lg { + max-width: $screen-lg; + } + + @include xl { + max-width: $screen-xl; + } + + @include 2xl { + max-width: $screen-2xl; + } +} +``` + +## 🎪 Motion Preferences + +```scss +// Respect user's motion preferences +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +// Dark mode support +@media (prefers-color-scheme: dark) { + :root { + --bg-primary: #{$gray-900}; + --text-primary: #{$gray-50}; + --glass-bg: rgba(0, 0, 0, 0.7); + --glass-border: rgba(255, 255, 255, 0.1); + } +} +``` + +## 🔧 Utility Classes + +### Display Utilities + +```scss +.hidden { display: none; } +.block { display: block; } +.inline-block { display: inline-block; } +.inline { display: inline; } +.flex { display: flex; } +.inline-flex { display: inline-flex; } +.grid { display: grid; } + +// Flexbox Utilities +.items-start { align-items: flex-start; } +.items-center { align-items: center; } +.items-end { align-items: flex-end; } +.justify-start { justify-content: flex-start; } +.justify-center { justify-content: center; } +.justify-end { justify-content: flex-end; } +.justify-between { justify-content: space-between; } +.flex-row { flex-direction: row; } +.flex-col { flex-direction: column; } +.flex-wrap { flex-wrap: wrap; } +.flex-1 { flex: 1 1 0%; } +.flex-auto { flex: 1 1 auto; } +``` + +### Spacing Utilities + +```scss +// Margin +@each $name, $size in ( + '0': $space-0, + '1': $space-1, + '2': $space-2, + '3': $space-3, + '4': $space-4, + '5': $space-5, + '6': $space-6, + '8': $space-8, + '10': $space-10, + '12': $space-12, + '16': $space-16 +) { + .m-#{$name} { margin: $size; } + .mt-#{$name} { margin-top: $size; } + .mr-#{$name} { margin-right: $size; } + .mb-#{$name} { margin-bottom: $size; } + .ml-#{$name} { margin-left: $size; } + .mx-#{$name} { + margin-left: $size; + margin-right: $size; + } + .my-#{$name} { + margin-top: $size; + margin-bottom: $size; + } +} + +// Padding (same pattern as margin) +``` + +### Text Utilities + +```scss +// Font Size +.text-xs { font-size: $text-xs; } +.text-sm { font-size: $text-sm; } +.text-base { font-size: $text-base; } +.text-lg { font-size: $text-lg; } +.text-xl { font-size: $text-xl; } +.text-2xl { font-size: $text-2xl; } +.text-3xl { font-size: $text-3xl; } +.text-4xl { font-size: $text-4xl; } + +// Font Weight +.font-thin { font-weight: $font-thin; } +.font-light { font-weight: $font-light; } +.font-normal { font-weight: $font-normal; } +.font-medium { font-weight: $font-medium; } +.font-semibold { font-weight: $font-semibold; } +.font-bold { font-weight: $font-bold; } + +// Text Alignment +.text-left { text-align: left; } +.text-center { text-align: center; } +.text-right { text-align: right; } +.text-justify { text-align: justify; } +``` + +--- + +*This design system provides the foundation for creating consistent, beautiful, and performant user interfaces across the MonacoUSA Portal.* \ No newline at end of file diff --git a/Design/mockups/dashboard-board-stunning.html b/Design/mockups/dashboard-board-stunning.html new file mode 100644 index 0000000..211da81 --- /dev/null +++ b/Design/mockups/dashboard-board-stunning.html @@ -0,0 +1,651 @@ + + + + + + MonacoUSA Portal - Board Dashboard + + + + + + + +
+
+
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+
+
+

MonacoUSA Portal

+

Board Executive Dashboard

+
+
+ + + + + +
+ + + + +
+
+

Board Executive

+

Administrative Access

+
+
+ Profile + +
+
+
+
+
+
+ + + + + +
+ +
+
+
+

Board Executive Dashboard

+

Real-time organization management and insights

+
+
+
+

Last Updated

+

2 min ago

+
+ +
+
+
+ + +
+ +
+
+
+ +
+
+ + +12% +
+
+

Total Members

+

287

+
+ Target: 300 +
+
+
+
+
+ + +
+
+
+ +
+
+ + +8% +
+
+

YTD Revenue

+

$43,050

+
+ Goal: $50,000 +
+
+
+
+
+ + +
+
+
+ +
+ ACTION +
+

Overdue Dues

+

43

+
+ Amount: $6,450 + +
+
+ + +
+
+
+ +
+
+ + +25% +
+
+

Avg Attendance

+

89%

+
+ Last 3 events +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ +
+
+

43 Members with Overdue Dues

+

Total outstanding amount: $6,450 • Average days overdue: 67

+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+

Dues Management

+
+ + + +
+
+ + +
+ +
+
+
+ Member +
+

Annette Anderson

+
+ ID: MUSA-16 + + 85 days overdue +
+
+
+
+
+

$150

+

Due Jun 6, 2024

+
+
+ + + +
+
+
+
+ + +
+
+
+ Member +
+

Danilo Copiz

+
+ ID: MUSA-19 + + 85 days overdue +
+
+
+
+
+

$150

+

Due Jun 6, 2024

+
+
+ + + +
+
+
+
+ + +
+
+
+ Member +
+

Ian Sosso

+
+ ID: MUSA-78 + + 81 days overdue +
+
+
+
+
+

$150

+

Due Jun 10, 2024

+
+
+ + + +
+
+
+
+
+ +
+ +
+
+
+ + +
+ +
+

Revenue Trend

+
+ +
+
+ + +
+

Quick Actions

+
+ + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/Design/mockups/dashboard-member-stunning.html b/Design/mockups/dashboard-member-stunning.html new file mode 100644 index 0000000..36cc431 --- /dev/null +++ b/Design/mockups/dashboard-member-stunning.html @@ -0,0 +1,601 @@ + + + + + + MonacoUSA Portal - Member Dashboard + + + + + + +
+
+
+
+
+ + +
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+

+ MonacoUSA Portal +

+

Excellence in Community

+
+
+ + + + + +
+ + + + + + + +
+
+

Matthew Ciaccio

+

Gold Member

+
+
+
+ Profile +
+
+
+
+
+
+ + + + + +
+ +
+
+
+
+

Welcome back, Matthew! 👋

+

Your membership is active and you have 2 upcoming events this week.

+ + +
+
+
+ Portal Status: Online +
+
+ + Members Online: 34 +
+
+ + Next Event: Dec 15 +
+
+
+
+
+ + +
+ +
+
+
+
+
+ +
+ ACTIVE +
+

Membership Status

+

Active

+
+
+ Expires + Dec 31, 2024 +
+
+
+
+ + +
+
+
+
+
+ +
+ DUE SOON +
+

Annual Dues

+

$150

+
+ +
+
+
+ + +
+
+
+
+
+ +
+ THIS YEAR +
+

Events Attended

+

12

+
+
+ Upcoming + 3 events +
+
+
+
+ + +
+
+
+
+
+ +
+ TOP 10% +
+

Member Points

+

2,450

+
+
+
+
+

550 points to Platinum

+
+
+
+
+ + +
+
+
+
+
+
+
+ +
+ FEATURED EVENT +
+

Annual Monaco Gala 2024

+

Join us for an elegant evening celebrating Monaco's heritage and culture. Black tie event with dinner, entertainment, and networking.

+
+
+ + December 15, 2024 +
+
+ + 7:00 PM - 11:00 PM +
+
+ + Monaco Embassy, Washington DC +
+
+
+
+ + +
+
+
+
+ + +
+ +
+
+
+

Recent Activity

+ +
+ +
+ +
+
+ +
+
+

New member joined

+

Sarah Johnson joined as a Silver member

+

2 hours ago

+
+
+ + +
+
+ +
+
+

Event reminder

+

Wine Tasting Event is coming up in 3 days

+

5 hours ago

+
+
+ + +
+
+ +
+
+

Achievement unlocked!

+

You've attended 10+ events this year

+

1 day ago

+
+
+
+
+
+ + +
+
+

Member Spotlight

+ +
+
+ Member +
+ +
+
+

John Smith

+

Board Member

+
+ + PLATINUM MEMBER +
+ +
+
+
+

15

+

Years

+
+
+

89

+

Events

+
+
+

5.2k

+

Points

+
+
+
+ + +
+
+
+
+
+ + +
+ +
+ + + + \ No newline at end of file diff --git a/components/ui/AnimatedNumber.vue b/components/ui/AnimatedNumber.vue new file mode 100644 index 0000000..a800ab3 --- /dev/null +++ b/components/ui/AnimatedNumber.vue @@ -0,0 +1,64 @@ + + + \ No newline at end of file diff --git a/components/ui/FloatingInput.vue b/components/ui/FloatingInput.vue new file mode 100644 index 0000000..c80afb7 --- /dev/null +++ b/components/ui/FloatingInput.vue @@ -0,0 +1,417 @@ + + + + + \ No newline at end of file diff --git a/components/ui/GlassCard.vue b/components/ui/GlassCard.vue new file mode 100644 index 0000000..a87559b --- /dev/null +++ b/components/ui/GlassCard.vue @@ -0,0 +1,276 @@ + + + + + \ No newline at end of file diff --git a/components/ui/Icon.vue b/components/ui/Icon.vue new file mode 100644 index 0000000..ce87314 --- /dev/null +++ b/components/ui/Icon.vue @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/components/ui/MonacoButton.vue b/components/ui/MonacoButton.vue new file mode 100644 index 0000000..7485fdd --- /dev/null +++ b/components/ui/MonacoButton.vue @@ -0,0 +1,329 @@ + + + + + \ No newline at end of file diff --git a/components/ui/StatsCard.vue b/components/ui/StatsCard.vue new file mode 100644 index 0000000..cb14e5c --- /dev/null +++ b/components/ui/StatsCard.vue @@ -0,0 +1,369 @@ + + + + + \ No newline at end of file diff --git a/components/ui/icons/ChevronDownIcon.vue b/components/ui/icons/ChevronDownIcon.vue new file mode 100644 index 0000000..7b0a457 --- /dev/null +++ b/components/ui/icons/ChevronDownIcon.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/nuxt.config.ts b/nuxt.config.ts index 4c4fb33..4121862 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -14,7 +14,7 @@ export default defineNuxtConfig({ console.log(`🌐 Server listening on http://${host}:${port}`) } }, - modules: ["vuetify-nuxt-module"], + modules: ["vuetify-nuxt-module", "@vueuse/motion/nuxt"], css: [], app: { head: { @@ -88,6 +88,70 @@ export default defineNuxtConfig({ appName: "MonacoUSA Portal", domain: process.env.NUXT_PUBLIC_DOMAIN || "https://portal.monacousa.org", keycloakIssuer: process.env.NUXT_KEYCLOAK_ISSUER || "https://auth.monacousa.org/realms/monacousa", + motion: { + directives: { + 'pop-bottom': { + initial: { + scale: 0, + opacity: 0, + y: 100 + }, + visible: { + scale: 1, + opacity: 1, + y: 0, + transition: { + type: 'spring', + stiffness: 250, + damping: 25 + } + } + }, + 'fade-in': { + initial: { + opacity: 0 + }, + enter: { + opacity: 1, + transition: { + duration: 600 + } + } + }, + 'slide-up': { + initial: { + y: 100, + opacity: 0 + }, + enter: { + y: 0, + opacity: 1, + transition: { + type: 'spring', + stiffness: 100, + damping: 20 + } + } + }, + 'glass-fade': { + initial: { + opacity: 0, + scale: 0.95, + filter: 'blur(10px)' + }, + enter: { + opacity: 1, + scale: 1, + filter: 'blur(0px)', + transition: { + duration: 500, + type: 'spring', + stiffness: 200 + } + } + } + } + } }, }, vuetify: { diff --git a/package-lock.json b/package-lock.json index fd410ac..cafea90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@types/jsonwebtoken": "^9.0.10", "@types/nodemailer": "^6.4.17", "@vite-pwa/nuxt": "^0.10.8", + "@vueuse/motion": "^3.0.3", "cookie": "^0.6.0", "formidable": "^3.5.4", "handlebars": "^4.7.8", @@ -5480,6 +5481,12 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -5995,6 +6002,64 @@ "vuetify": "^3.0.0" } }, + "node_modules/@vueuse/core": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.8.0.tgz", + "integrity": "sha512-rmBcgpEpxY0ZmyQQR94q1qkUcHREiLxQwNyWrtjMDipD0WTH/JBcAt0gdcn2PsH0SA76ec291cHFngmyaBhlxA==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "13.8.0", + "@vueuse/shared": "13.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.8.0.tgz", + "integrity": "sha512-BYMp3Gp1kBUPv7AfQnJYP96mkX7g7cKdTIgwv/Jgd+pfQhz678naoZOAcknRtPLP4cFblDDW7rF4e3KFa+PfIA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/motion": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@vueuse/motion/-/motion-3.0.3.tgz", + "integrity": "sha512-4B+ITsxCI9cojikvrpaJcLXyq0spj3sdlzXjzesWdMRd99hhtFI6OJ/1JsqwtF73YooLe0hUn/xDR6qCtmn5GQ==", + "license": "MIT", + "dependencies": { + "@vueuse/core": "^13.0.0", + "@vueuse/shared": "^13.0.0", + "defu": "^6.1.4", + "framesync": "^6.1.2", + "popmotion": "^11.0.5", + "style-value-types": "^5.1.2" + }, + "optionalDependencies": { + "@nuxt/kit": "^3.13.0" + }, + "peerDependencies": { + "vue": ">=3.0.0" + } + }, + "node_modules/@vueuse/shared": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.8.0.tgz", + "integrity": "sha512-x4nfM0ykW+RmNJ4/1IzZsuLuWWrNTxlTWUiehTGI54wnOxIgI9EDdu/O5S77ac6hvQ3hk2KpOVFHaM0M796Kbw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, "node_modules/@whatwg-node/disposablestack": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz", @@ -8853,6 +8918,21 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framesync": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz", + "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==", + "license": "MIT", + "dependencies": { + "tslib": "2.4.0" + } + }, + "node_modules/framesync/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", @@ -9378,6 +9458,12 @@ "he": "bin/he" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", @@ -12871,6 +12957,24 @@ "pathe": "^2.0.3" } }, + "node_modules/popmotion": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.5.tgz", + "integrity": "sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==", + "license": "MIT", + "dependencies": { + "framesync": "6.1.2", + "hey-listen": "^1.0.8", + "style-value-types": "5.1.2", + "tslib": "2.4.0" + } + }, + "node_modules/popmotion/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -14876,6 +14980,22 @@ "integrity": "sha512-FL8EeKFFyNQv5cMnXI31CIMCsFarSVI2bF0U0ImeNE3g/F1IvJQyqzOXxPBRXiwQfyBTlbNe88jh1jFW0O/jiQ==", "license": "ISC" }, + "node_modules/style-value-types": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.1.2.tgz", + "integrity": "sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==", + "license": "MIT", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "2.4.0" + } + }, + "node_modules/style-value-types/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/stylehacks": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.6.tgz", diff --git a/package.json b/package.json index fb49f64..65d6a7d 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@types/jsonwebtoken": "^9.0.10", "@types/nodemailer": "^6.4.17", "@vite-pwa/nuxt": "^0.10.8", + "@vueuse/motion": "^3.0.3", "cookie": "^0.6.0", "formidable": "^3.5.4", "handlebars": "^4.7.8", diff --git a/pages/dashboard/mockup.vue b/pages/dashboard/mockup.vue new file mode 100644 index 0000000..ab4bbff --- /dev/null +++ b/pages/dashboard/mockup.vue @@ -0,0 +1,613 @@ + + + + + \ No newline at end of file diff --git a/pages/events/mockup.vue b/pages/events/mockup.vue new file mode 100644 index 0000000..dcbd491 --- /dev/null +++ b/pages/events/mockup.vue @@ -0,0 +1,710 @@ + + + + + \ No newline at end of file