diff --git a/.agent/development/SKILL.md b/.agent/development/SKILL.md deleted file mode 100644 index 7e172b2..0000000 --- a/.agent/development/SKILL.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -name: CodeBridger Development Skill -description: Core development guidelines and documentation for the Subturtle/CodeBridger ecosystem. Triggered when working on dashboard-app or server. ---- - -# Development Guidelines - -## General Principles - -- **Modularity**: Prioritize modularity in all code changes. Organize logic into distinct modules (Server-side) or reusable components (Frontend). -- **ClickUp Integration**: - - Task management primarily relies on ClickUp. - - Always reference the ClickUp task ID in commit messages. Format: `feat: #taskid message`. -- **Communication**: - - Favor answering questions and providing explanations over direct code modifications unless explicitly requested. - - Ensure all explanations are clear and provide necessary context. - -## Framework Documentation - -Always refer to the official documentation for package-specific implementations: - -### Server-Side (@modular-rest/server) -- **Primary Docs**: [modular-rest_server.md](./modular-rest_server.md) -- **Key Patterns**: - - Use `defineCollection` in `db.ts` for database models. - - Use `defineFunction` in `functions.ts` for API logic. - - Avoid manual router creation unless necessary (`router.ts`). - -### Frontend-Side (@modular-rest/client) -- **Primary Docs**: [modular-rest_client.md](./modular-rest_client.md) -- **Key Patterns**: - - Reference the JS client for consuming services and calling server functions. - -### UI Components (lib-vue-components) -- **Primary Docs**: [lib-vue-components.md](./lib-vue-components.md) -- **Key Patterns**: - - Import components directly from `@codebridger/lib-vue-components` as needed (e.g., `import { Button } from '@codebridger/lib-vue-components'`). - - Follow the design system guidelines for consistent aesthetics. - - ---- - -You must read the specific documentation files listed above before proposing or implementing any technical changes related to these packages. \ No newline at end of file diff --git a/.agent/e2e/SKILL.md b/.agent/e2e/SKILL.md deleted file mode 100644 index b636dd5..0000000 --- a/.agent/e2e/SKILL.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: e2e -description: End-to-end navigation and testing guide for Subturtle Dashboard ---- - -This skill provides specific instructions for navigating and testing the Subturtle Dashboard application using browser tools. - -## Prerequisites -1. **Server**: Ensure the server is running (usually on port 8080). -2. **Frontend**: Ensure the frontend is running (usually on port 3000). - -## Authentication Flow -The application uses hash-based routing (`hashMode: true` in Nuxt config). To authenticate via token, you MUST include the `#` character in the URL. - -**Correct URL Template:** -`http://localhost:3000/#/auth/login_with_token?token={YOUR_TOKEN}` - -### Steps for Browser Agents: -1. **Navigate**: Use the `open_browser_url` tool with the correct hash-based login URL. -2. **Wait for Redirect**: The `login_with_token` page is a redirection page. Wait at least 3 seconds for the `onMounted` hook to process the token and redirect to the dashboard. -3. **Verify Dashboard**: After redirection, verify you are on `/#/` or another authenticated route. Use `capture_browser_screenshot` to confirm the UI has loaded. -4. **Inspect UI**: Once logged in, use the navigation menu or direct hash-links to find the specific page. - -## Navigation Structure -- Home/Overview: `/#/` -- Board (Learning System): `/#/board` -- Statistic: `/#/statistic` -- Sessions: `/#/sessions` -- Settings: `/#/settings` - -## Troubleshooting -- **Blank Page**: Check browser console for authentication errors. -- **Login Redirect**: If redirected to `/#/auth/login`, the token might be invalid or expired. -- **Missing Hash**: Always ensure the URL contains `/#/` after the origin. -- **Login Issue**: If you are not logged in, try to store the token in the browser's local storage `token={YOUR_TOKEN}` and then navigate to the dashboard. \ No newline at end of file diff --git a/.agent/skills/backend/SKILL.md b/.agent/skills/backend/SKILL.md new file mode 100644 index 0000000..193f733 --- /dev/null +++ b/.agent/skills/backend/SKILL.md @@ -0,0 +1,28 @@ +--- +name: Backend Development +description: Guidelines for Server-side development using Modular Rest, Database schemas, and Business Logic. +--- + +# Backend Development Skill + +## 1. Core Principles +- **Modularity**: Organize logic into distinct, independent modules. Each module should have a single responsibility. +- **Testing**: Write unit tests for core logic and services. +- **Documentation**: Use JSDoc for functions to document parameters and return values. +- **Workflow**: Always reference the ClickUp task ID in commit messages (e.g., `feat: #taskid message`). + +## 2. Technology Stack +- **Framework**: Modular Rest Server (@modular-rest/server) +- **Database**: MongoDB (via `defineCollection`) + +## 3. Documentation Reference +**You MUST read the following file for API details:** +- [Modular Rest Server Docs](./modular-rest_server.md) + +## 4. Key Patterns +- **Database Models**: Use `defineCollection` in `db.ts` files within modules. +- **API Functions**: Use `defineFunction` in `functions.ts` files. +- **Routing**: Avoid manual router creation; let the framework handle it. + +## 5. Directory Structure +Code should be written in `/Users/navid-shad/Projects/CodeBridger/learn-by-subtitle/dashboard-app/server`. diff --git a/.agent/development/modular-rest_server.md b/.agent/skills/backend/modular-rest_server.md similarity index 100% rename from .agent/development/modular-rest_server.md rename to .agent/skills/backend/modular-rest_server.md diff --git a/.agent/skills/frontend/SKILL.md b/.agent/skills/frontend/SKILL.md new file mode 100644 index 0000000..3824523 --- /dev/null +++ b/.agent/skills/frontend/SKILL.md @@ -0,0 +1,32 @@ +--- +name: Frontend Logic +description: Guidelines for Client-side logic, State Management (Pinia), API Integration, and App Navigation. +--- + +# Frontend Logic Skill + +## 1. Core Principles +- **State Management**: Use Pinia for global state. +- **API Integration**: Use `@modular-rest/client` to call server functions. +- **Testing**: Implement integration tests for complex component interactions. +- **Workflow**: Always reference the ClickUp task ID in commit messages (e.g., `feat: #taskid message`). + +## 2. Documentation Reference +**You MUST read the following file for API Client details:** +- [Modular Rest Client Docs](./modular-rest_client.md) + +## 3. Navigation & Auth Flow +The application uses hash-based routing (`/#/`). + +### Common Routes +- Home: `/#/` +- Board: `/#/board` +- Settings: `/#/settings` + +### Authentication +- Token is stored in `localStorage` key `token`. +- If redirected to login, verify token presence. + +## 4. Key Patterns +- **Services**: Import `functionProvider` from `@modular-rest/client` to execute backend functions. +- **Composables**: Use Vue composables for reusable logic. diff --git a/.agent/development/modular-rest_client.md b/.agent/skills/frontend/modular-rest_client.md similarity index 100% rename from .agent/development/modular-rest_client.md rename to .agent/skills/frontend/modular-rest_client.md diff --git a/.agent/skills/frontend_design/SKILL.md b/.agent/skills/frontend_design/SKILL.md new file mode 100644 index 0000000..dc0317a --- /dev/null +++ b/.agent/skills/frontend_design/SKILL.md @@ -0,0 +1,122 @@ +--- +name: Frontend Design System +description: Comprehensive guide for creating premium, high-fidelity UI layouts using the project's Vue component library and Tailwind CSS. +--- + +# Frontend Design System + +This skill provides the standards and patterns for building user interfaces in the dashboard application. The goal is to create a **premium, dynamic, and highly polished** user experience that "wows" the user. + +## 1. Design Philosophy + +- **High-End Aesthetics**: We do not build "MVP-looking" apps. We build refined, polished interfaces. +- **Glassmorphism & Depth**: Utilize layers, blurs (`backdrop-blur-xl`), and subtle transparencies (`bg-white/40`) to create depth. +- **Vibrant Colors**: Use the project's `primary` and `secondary` palette, but often via gradients or low-opacity tints (`bg-primary/10`) rather than solid blocks of harsh color. +- **Dynamic Motion**: Nothing should feel static. Smooth transitions (`duration-500`, `duration-700`), micro-interactions on hover, and entrance animations are required. + +## 2. Component Usage + +All standard UI elements must come from the internal component library. + +**Reference Documentation:** +- [UI Component Library (lib-vue-components)](./lib-vue-components.md) - Contains full list of available components and their props. + +```typescript +// Import path +import { Card, Button, Icon } from '@codebridger/lib-vue-components/elements.ts'; +import { Modal } from '@codebridger/lib-vue-components/complex.ts'; +``` + +### Key Components +- **Card**: The building block for content. +- **Button**: Use for actions. +- **Icon**: Wrapper for Iconify icons. PREFERRED SET: `iconify solar--*-bold-duotone` or `*-bold`. +- **PageHeader**: Standard top-of-page layout with title, subtitle, and actions. +- **Breadcrumb**: Navigation hierarchy component. + +## 3. Layout Patterns + +### Main Page Shell +Pages normally live within a `DashboardShell` (via `default` layout). Content should be centered with max-width. + +```vue + +``` + +### Card Styling +Cards should rarely be just plain rectangles. + +**Premium Card Recipe:** +- **Rounding**: `rounded-[2.5rem]` or `rounded-3xl` (generous curves). +- **Background**: `bg-white dark:bg-gray-800`. +- **Shadow**: Light idle shadow `shadow-[0_4px_20px_rgba(0,0,0,0.03)]` -> Deep hover shadow `hover:shadow-[0_40px_80px_rgba(var(--primary-rgb),0.15)]`. +- **Interaction**: `group hover:-translate-y-3 transition-all duration-700`. +- **Decorations**: Use absolute positioned gradients or icons in the background of cards to add texture. + +## 4. Typography Standards + +- **Titles (H1-H2)**: `font-black`, `tracking-tight`. +- **Body**: `font-medium` (avoid thin weights for body text to maintain legibility and premium feel). +- **Labels/Meta**: `text-[10px]` or `text-xs`, `font-bold`, `uppercase`, `tracking-widest` (typographic spacing is key for the premium look). +- **Colors**: + - Primary text: `text-gray-900` / `dark:text-white` + - Secondary text: `text-gray-500` / `dark:text-gray-400` + - Accent text: `text-primary` + +## 5. Visual Effects & Assets + +### Gradients +Use gradients to create "glows". +- *Example*: `bg-gradient-to-br from-primary via-primary-dark to-secondary` + +### Glassmorphism +- Use `backdrop-blur-md` or `backdrop-blur-xl`. +- Combine with `bg-white/10` or `bg-white/70`. +- Add `border border-white/20` for the "glass edge" look. + +### Background Elements +Add "blobs" behind the main content to avoid empty whitespace looking boring. +```html +
+``` + +## 6. Development Checklist + +When creating a new page or component: +1. [ ] Did I use `Card` and `Button` from the library? +2. [ ] Are the borders rounded enough (`rounded-2xl+`)? +3. [ ] Is there an entrance animation (e.g., `animate-fade-in-up`)? +4. [ ] Are interactable elements responsive to hover (scale, shadow, lift)? +5. [ ] Is Dark Mode supported (`dark:` variants)? +6. [ ] Did I use the "Solar" icon set (`iconify solar--...`)? +7. [ ] Is the typography hierarchy clear (Big titles, tiny uppercase labels)? diff --git a/.agent/development/lib-vue-components.md b/.agent/skills/frontend_design/lib-vue-components.md similarity index 100% rename from .agent/development/lib-vue-components.md rename to .agent/skills/frontend_design/lib-vue-components.md diff --git a/frontend/components/Leitner/BoxStats.vue b/frontend/components/Leitner/BoxStats.vue index 41f44de..be45c70 100644 --- a/frontend/components/Leitner/BoxStats.vue +++ b/frontend/components/Leitner/BoxStats.vue @@ -3,12 +3,13 @@
-

Leitner Progress

- -
+

{{ $t('smart_review.progress') }}

+ +

No phrases in the system yet.

- + @@ -17,28 +18,30 @@
@@ -274,12 +277,18 @@ function close() {
- Total: {{ totalPhrases }} phrases + {{ $t('smart_review.total_phrases', { count: totalPhrases }) + }}
- - Page {{ page }} - + + {{ $t('smart_review.page', { + page: + page }) + }} +
diff --git a/frontend/components/Leitner/LeitnerSettings.vue b/frontend/components/Leitner/LeitnerSettings.vue index 7c6d1b9..80c1c6c 100644 --- a/frontend/components/Leitner/LeitnerSettings.vue +++ b/frontend/components/Leitner/LeitnerSettings.vue @@ -4,10 +4,11 @@
-
-

Total Progress

+
+

{{ + $t('smart_review.total_progress') }}

{{ stats?.totalItems || 0 }}

-

Collected phrases

+

{{ $t('smart_review.collected_phrases') }}

@@ -16,11 +17,12 @@ -
-

Next Session

+
+

{{ + $t('smart_review.next_session') }}

{{ localSettings.reviewHour }}:00

-

{{ localSettings.reviewInterval === 1 ? 'Daily' : 'Every ' + - localSettings.reviewInterval + ' days' }} reminder

+

{{ localSettings.reviewInterval === 1 ? $t('smart_review.daily') : + $t('smart_review.every_days_reminder', { days: localSettings.reviewInterval }) }}

@@ -29,10 +31,11 @@ -
-

Boxes Active

+
+

{{ + $t('smart_review.levels_active') }}

{{ localSettings.totalBoxes }}

-

Step progression

+

{{ $t('smart_review.step_progression') }}

@@ -41,7 +44,7 @@
- +
@@ -49,9 +52,10 @@
-

Leitner System Configuration

+

{{ $t('smart_review.settings') }} +

- Configure your spaced repetition journey. Items move down the chain as you learn them. + {{ $t('smart_review.settings_desc') }}

@@ -66,11 +70,11 @@
- +
-

Automatically add any new - saved phrase to Box 1

+

{{ + $t('smart_review.auto_entry_desc') }}

@@ -83,10 +87,12 @@
- +
-

Total number of boxes in the chain

+

{{ $t('smart_review.settings_desc') }} +

- + -

Max phrases to review per session

+

{{ $t('smart_review.max_phrases_desc') + }}

-
+
- +
-

Session frequency and time

+

{{ + $t('smart_review.session_frequency_desc') }}

- Each + {{ $t('smart_review.each') }} - day at + {{ + $t('smart_review.day_at') }}
@@ -148,7 +157,7 @@
-
{{ getItemCount(index) }} - Cards + {{ + $t('smart_review.cards') }}

- Box {{ index + 1 }} + {{ $t('smart_review.level_number', { number: index + 1 }) }} Entrance + class="px-1.5 py-0 rounded text-[9px] bg-primary/10 text-primary uppercase font-bold border border-primary/20">{{ + $t('smart_review.entrance') }} Mature + class="px-1.5 py-0 rounded text-[9px] bg-success/10 text-success uppercase font-bold border border-success/20">{{ + $t('smart_review.mature') }}

-

Level {{ index + 1 }} - of knowledge retention

+

{{ + $t('smart_review.level_retention_desc', { number: index + 1 }) }}

@@ -197,14 +208,15 @@
days + class="absolute right-2 top-2 text-[10px] text-gray-400 pointer-events-none">{{ + $t('smart_review.days') }}
@@ -213,13 +225,14 @@
items + class="absolute right-2 top-2 text-[10px] text-gray-400 pointer-events-none">{{ + $t('smart_review.items') }}
@@ -230,7 +243,7 @@ - Manage + {{ $t('smart_review.manage') }} @@ -242,22 +255,22 @@
+ class="fixed bottom-6 left-1/2 -translate-x-1/2 w-[95%] max-w-2xl flex items-center justify-between gap-4 rounded-2xl border border-white/20 bg-white/70 p-4 shadow-2xl backdrop-blur-xl dark:border-gray-700/30 dark:bg-gray-900/70">
- {{ settingsDirty ? 'Unsaved changes' : 'Settings synced' }} + {{ settingsDirty ? $t('smart_review.unsaved_changes') : $t('smart_review.settings_synced') }}
- + - + - Save Preferences + {{ $t('smart_review.save_preferences') }} @@ -342,6 +357,7 @@ import HourSelector from '~/components/material/HourSelector.vue'; import { functionProvider } from '@modular-rest/client'; import { useProfileStore } from '~/stores/profile'; import { storeToRefs } from 'pinia'; +import { useI18n } from 'vue-i18n'; interface Settings { dailyLimit: number; totalBoxes: number; @@ -363,7 +379,9 @@ const props = defineProps<{ const emit = defineEmits(['saved', 'reset']); const profileStore = useProfileStore(); + const { authUser } = storeToRefs(profileStore); +const { t } = useI18n(); const loading = ref(false); const resetting = ref(false); @@ -481,7 +499,7 @@ async function performSave(toggleModal: (state: boolean) => void) { emit('saved'); } catch (e) { console.error(e); - toastError('Failed to save settings'); + toastError(t('smart_review.failed_save')); } finally { loading.value = false; } @@ -498,10 +516,10 @@ async function performReset(toggleModal: (state: boolean) => void) { }); toggleModal(false); emit('reset'); - toastSuccess('System has been reset.'); + toastSuccess(t('smart_review.system_reset_success')); } catch (e) { console.error(e); - toastError('Failed to reset system'); + toastError(t('smart_review.failed_reset')); } finally { resetting.value = false; } diff --git a/frontend/components/bundle/GenerativeCard.vue b/frontend/components/bundle/GenerativeCard.vue index b0bf2bd..452b3bd 100644 --- a/frontend/components/bundle/GenerativeCard.vue +++ b/frontend/components/bundle/GenerativeCard.vue @@ -20,51 +20,51 @@ diff --git a/frontend/components/common/Breadcrumb.vue b/frontend/components/common/Breadcrumb.vue new file mode 100644 index 0000000..9317d02 --- /dev/null +++ b/frontend/components/common/Breadcrumb.vue @@ -0,0 +1,39 @@ + + + diff --git a/frontend/components/common/PageHeader.vue b/frontend/components/common/PageHeader.vue new file mode 100644 index 0000000..707b723 --- /dev/null +++ b/frontend/components/common/PageHeader.vue @@ -0,0 +1,51 @@ + + + diff --git a/frontend/components/partial/ProfileButton.vue b/frontend/components/partial/ProfileButton.vue index c4a8053..25cad71 100644 --- a/frontend/components/partial/ProfileButton.vue +++ b/frontend/components/partial/ProfileButton.vue @@ -23,27 +23,21 @@
  • - + {{ t('profile.profile') }}
  • - + - Leitner Preferences + {{ t('smart_review.settings') }}
  • @@ -77,34 +71,34 @@ diff --git a/frontend/components/practice/LeitnerReviewSession.vue b/frontend/components/practice/LeitnerReviewSession.vue new file mode 100644 index 0000000..4a29129 --- /dev/null +++ b/frontend/components/practice/LeitnerReviewSession.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/frontend/composables/useDashboardNavigatorItems.ts b/frontend/composables/useDashboardNavigatorItems.ts index 57a5c08..280f00e 100644 --- a/frontend/composables/useDashboardNavigatorItems.ts +++ b/frontend/composables/useDashboardNavigatorItems.ts @@ -17,6 +17,11 @@ export const useDashboardNavigatorItems = (): Array => { { title: t('practice.title'), children: [ + { + title: t('smart_review.settings'), + icon: 'IconSettings', + to: '/settings/preferences', + }, { title: t('activities.title'), icon: 'iconify solar--rocket-2-bold-duotone', diff --git a/frontend/locales/en.json b/frontend/locales/en.json index 9e5ca11..f968a99 100644 --- a/frontend/locales/en.json +++ b/frontend/locales/en.json @@ -229,6 +229,75 @@ "recent-lectures": "Recent AI Lectures", "view-all": "View All" }, + "smart_review": { + "title": "Smart Review", + "settings": "Smart Review Settings", + "settings_desc": "Configure your spaced repetition journey. Items move down the chain as you learn them.", + "reset_title": "Reset Smart Review", + "reset_confirm": "Are you sure you want to reset your entire review progress?", + "level": "Level", + "levels": "Levels", + "levels_active": "Levels Active", + "total_levels": "Total Levels", + "level_number": "Level {number}", + "target_level": "Target Level", + "move_to_level": "Move to Level {number}", + "remove_from_level": "Remove from Level {number}", + "add_to_level": "Add to Level {number}", + "auto_entry_desc": "Automatically add any new saved phrase to Level 1", + "progress": "Review Progress", + "save_confirm_desc": "You are about to update your review intervals. Existing items might be rescheduled.", + "total_progress": "Total Progress", + "collected_phrases": "Collected phrases", + "next_session": "Next Session", + "daily": "Daily", + "every_days_reminder": "Every {days} days reminder", + "step_progression": "Step progression", + "auto_entry": "Auto-Entry", + "global_daily_limit": "Global Daily Limit", + "max_phrases_desc": "Max phrases to review per session", + "review_interval": "Review Interval", + "session_frequency_desc": "Session frequency and time", + "each": "Each", + "day_at": "day at", + "cards": "Cards", + "entrance": "Entrance", + "mature": "Mature", + "level_retention_desc": "Level {number} of knowledge retention", + "interval": "Interval", + "days": "days", + "quota": "Cards Per Session", + "items": "items", + "manage": "Manage", + "unsaved_changes": "Unsaved changes", + "settings_synced": "Settings synced", + "reset_progress": "Reset Progress", + "dangerous_action": "Dangerous Action!", + "reset_warning": "This cannot be undone.", + "keep_everything": "Keep Everything", + "confirm_wipe": "Confirm Wipe", + "confirm_save": "Confirm Save", + "save_preferences": "Save Preferences", + "review_changes": "Review Changes", + "go_back": "Go Back", + "apply_now": "Apply Now", + "failed_save": "Failed to save settings", + "system_reset_success": "System has been reset.", + "failed_reset": "Failed to reset system", + "forgot": "Forgot", + "learned": "Learned", + "press_key_or_key": "Press {key1} or {key2}", + "press_space_to_flip": "Press Space to flip the card", + "search_phrases_placeholder": "Search phrases...", + "all_bundles": "All Bundles", + "loading": "Loading...", + "no_phrases_found": "No phrases found.", + "total_phrases": "Total: {count} phrases", + "previous": "Previous", + "page": "Page {page}", + "next": "Next", + "select_phrase": "Select Phrase" + }, "board": { "no_activities": "No activities right now", "all_caught_up": "You are all caught up! Check back later.", diff --git a/frontend/pages/bundles/[id].vue b/frontend/pages/bundles/[id].vue index a232351..11e064e 100644 --- a/frontend/pages/bundles/[id].vue +++ b/frontend/pages/bundles/[id].vue @@ -1,161 +1,322 @@ diff --git a/frontend/pages/bundles/index.vue b/frontend/pages/bundles/index.vue index 08061c8..3673414 100644 --- a/frontend/pages/bundles/index.vue +++ b/frontend/pages/bundles/index.vue @@ -1,123 +1,136 @@ diff --git a/frontend/pages/practice/bundle-review.vue b/frontend/pages/practice/bundle-review.vue new file mode 100644 index 0000000..2b9f1e9 --- /dev/null +++ b/frontend/pages/practice/bundle-review.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/frontend/pages/practice/review.vue b/frontend/pages/practice/review.vue index 7ac0613..b092736 100644 --- a/frontend/pages/practice/review.vue +++ b/frontend/pages/practice/review.vue @@ -1,85 +1,12 @@ + +