# CannaManage — User Stories **Version:** 1.0 **Date:** 2026-06-13 **Status:** Complete --- ## Persona: Admin/Staff (Vereinsverwaltung) ### US-A01: Admin Login **As an** admin, **I want to** log in with my email and password, **So that** I can access the management dashboard securely. **Acceptance Criteria:** - Login page displays email and password fields - Form validates email format (Zod schema) - Empty fields trigger validation errors with `aria-invalid` - Invalid credentials show localized error message - Successful login redirects to `/dashboard` - Password field is masked (type="password") - Form is keyboard-navigable (Tab + Enter) --- ### US-A02: Dashboard Overview **As an** admin, **I want to** see KPI cards on my dashboard, **So that** I can monitor club status at a glance. **Acceptance Criteria:** - Dashboard shows 4 KPI cards: Active Members, Distributions Today, Stock Level, Monthly Quota Used - Quick actions section provides shortcuts to common tasks - Recent distributions list shows latest activity - Stock by strain visualization is present - Page is responsive (cards stack on mobile) - Dark/light mode renders correctly --- ### US-A03: Member List Management **As an** admin, **I want to** view, search, and paginate through members, **So that** I can quickly find and manage club members. **Acceptance Criteria:** - Member table displays: name, email, status, joined date, member number - Status badges show Active/Inactive/Suspended with color coding - Search input filters members by name or email - Pagination controls navigate between pages - "Add Member" button navigates to creation form - Clicking a member navigates to their detail page --- ### US-A04: Add New Member **As an** admin, **I want to** register a new member with their details, **So that** they can start receiving distributions. **Acceptance Criteria:** - Form includes: first name, last name, email, date of birth, phone, notes - All required fields show validation errors when empty - Date of birth calculates age for KCanG compliance checks - Email must be unique (backend validation) - Success redirects to member detail page - Cancel returns to member list without saving --- ### US-A05: Edit Member Details **As an** admin, **I want to** edit an existing member's information, **So that** I can keep records current. **Acceptance Criteria:** - Form pre-fills with existing member data - All editable fields can be updated - Status can be changed (Active/Inactive/Suspended) - Changes are saved with confirmation - Audit event is logged on status change --- ### US-A06: Distribution List **As an** admin, **I want to** view all cannabis distributions with filters, **So that** I can track dispensing history. **Acceptance Criteria:** - Table shows: date, member name, strain, amount (grams), recorded by - Filter by time period: today, this week, this month, all - Sort by date (newest first by default) - "New Distribution" button starts the wizard - Total distributed amount shown in header --- ### US-A07: Distribution Wizard (4-Step) **As an** admin, **I want to** record a distribution through a guided wizard, **So that** quota limits are enforced before dispensing. **Acceptance Criteria:** - **Step 1:** Select member (search by name/number) - **Step 2:** Quota check shows daily/monthly remaining (25g daily, 50g monthly) - Under-21 shows 30g monthly limit and 10% THC restriction - Blocks progression if limits exceeded - **Step 3:** Select strain + enter amount (grams) - THC% shown per strain for under-21 verification - Amount cannot exceed available batch stock - **Step 4:** Confirmation summary → submit - Success creates distribution record + audit event - Back navigation between steps preserves data --- ### US-A08: Stock/Batch Management **As an** admin, **I want to** manage cannabis batches in inventory, **So that** I can track available stock. **Acceptance Criteria:** - Batch list shows: strain, THC%, CBD%, available grams, status - Overview cards: total stock, active batches, low stock alerts - Filter by strain or batch status - "Add Batch" button opens creation form - Stock levels update after distributions --- ### US-A09: Add New Batch **As an** admin, **I want to** register a new cannabis batch, **So that** it becomes available for distribution. **Acceptance Criteria:** - Form includes: strain name, THC%, CBD%, total grams, harvest date, notes - THC% and CBD% are numeric with validation (0-100) - Total grams must be positive - Batch gets unique ID and "Available" status - Can link to a grow entry (traceability) --- ### US-A10: Grow Calendar **As an** admin, **I want to** track plant grows through their lifecycle stages, **So that** I can manage cultivation from seed to harvest. **Acceptance Criteria:** - Calendar/list shows all active grows with current stage - 7 stages: Seedling → Vegetative → Flowering → Harvest → Drying → Curing → Complete - Stage progression is sequential (can't skip) - Each grow shows: strain, start date, current stage, days in stage - Color-coded stage indicators --- ### US-A11: Grow Detail **As an** admin, **I want to** manage a specific grow entry in detail, **So that** I can record sensors, photos, and feeding. **Acceptance Criteria:** - Sensor readings displayed: temperature, humidity, CO2, pH, EC - Photo gallery with upload capability - Feeding log with date, nutrients, amount - Timeline showing stage transitions - "Advance Stage" button with confirmation - Harvest → links to batch creation (traceability) --- ### US-A12: Reports **As an** admin, **I want to** generate compliance reports, **So that** I can satisfy regulatory requirements. **Acceptance Criteria:** - Three report types: Monthly Report, Member List, Recall Report - Preview mode shows report content in-page - PDF download generates branded document - CSV export for data analysis - Monthly report includes: distributions count, total grams, member activity - Recall report traces a batch to all distribution recipients --- ### US-A13: Audit Log **As an** admin, **I want to** view an immutable audit trail, **So that** all actions are traceable for compliance. **Acceptance Criteria:** - Shows 18+ event types (MEMBER_CREATED, DISTRIBUTION_RECORDED, BATCH_ADDED, etc.) - Filter by event type, date range, actor - Each entry shows: timestamp, event type, actor, details - Tamper-proof indicator (hash chain) - PDF export of filtered results - 10-year retention policy displayed - Log entries cannot be deleted (REVOKE DELETE) --- ### US-A14: Staff Management **As an** admin, **I want to** invite and manage staff accounts, **So that** I can control who has access. **Acceptance Criteria:** - Staff list shows: name, email, role, permissions, last active - "Invite Staff" button opens invitation form (email + role) - Permission checkboxes for granular access control - "Revoke Access" button with confirmation dialog - Prevention officer role limit enforced (max per KCanG) - Invite sends email with token link --- ### US-A15: Billing & Subscription **As an** admin, **I want to** manage my club's subscription plan, **So that** I can access features appropriate to our size. **Acceptance Criteria:** - Current plan displayed with usage stats - Three tiers: Starter (€19/≤30 members), Pro (€49/≤100 members), Enterprise - Upgrade/downgrade available - Payment methods: SEPA, PayPal, Card (via Stripe) - Billing history with invoices - 3-month free trial for new clubs --- ### US-A16: Privacy/DSGVO Settings **As an** admin, **I want to** handle data privacy requests, **So that** my club complies with GDPR. **Acceptance Criteria:** - Data Export (Art. 15): Generate JSON export of all member data - Account Deletion (Art. 17): Delete member with confirmation - Consent management overview - Data processing agreement reference - Last export/deletion timestamp shown --- ### US-A17: Protected Route Access Control **As a** system, **I want to** redirect unauthenticated users to login, **So that** admin pages are secured. **Acceptance Criteria:** - All admin routes redirect to `/login` when not authenticated - Redirect preserves `callbackUrl` parameter - After login, user returns to originally requested page - Session expiry triggers redirect --- ## Persona: Member (Portal-Nutzer) ### US-M01: Member Portal Login **As a** member, **I want to** log in to my personal portal, **So that** I can view my quota and history. **Acceptance Criteria:** - Portal login page at `/portal-login` with email + password - Separate from admin login (different auth flow) - Link to admin login ("Staff login") - Successful login redirects to `/portal/dashboard` - Invalid credentials show error --- ### US-M02: Portal Dashboard / Quota View **As a** member, **I want to** see my daily and monthly quota usage, **So that** I know how much I can still receive. **Acceptance Criteria:** - Daily quota ring: X.Xg / 25g used (visual circle) - Monthly quota ring: X.Xg / 50g used (visual circle) - Under-21 shows 30g monthly limit - Last distribution info: strain, amount, date - Quick info section with member number and club name - Navigation links to history and profile --- ### US-M03: Distribution History **As a** member, **I want to** view my past distributions, **So that** I can track what I received. **Acceptance Criteria:** - Table showing: date, strain, amount (grams), recorded by - Sorted by date (newest first) - Pagination for many entries - Tamper-proof indicator per entry - Navbar with portal navigation - Total received this month displayed --- ### US-M04: Member Profile **As a** member, **I want to** view and update my personal information, **So that** my records stay current. **Acceptance Criteria:** - Personal info displayed: name, email, member number, date of birth - Password change section (current + new + confirm) - Language preference toggle (DE/EN) - Theme preference (dark/light/system) - Save button for changes - Read-only fields clearly distinguished --- ### US-M05: Portal Navigation **As a** member, **I want to** navigate between portal pages easily, **So that** I can access all self-service features. **Acceptance Criteria:** - Top navbar with links: Dashboard, History, Profile - Active page indicator in navigation - Footer with legal links - No sidebar (cleaner portal layout) - Responsive at all breakpoints --- ## Persona: Visitor (Öffentlicher Zugang) ### US-V01: Pricing Page **As a** visitor, **I want to** compare subscription plans, **So that** I can decide which tier to purchase. **Acceptance Criteria:** - Three plan cards: Starter, Pro, Enterprise - Feature comparison matrix - Price displayed per plan (€19/€49/Custom) - FAQ section for common questions - CTA button per plan ("Get Started" / "Contact Us") - Responsive layout (cards stack on mobile) --- ### US-V02: Legal Pages (Impressum, Datenschutz, AGB) **As a** visitor, **I want to** read legal information, **So that** I understand the terms. **Acceptance Criteria:** - `/impressum` — Legal notice with company info - `/datenschutz` — Privacy policy (DSGVO-compliant) - `/agb` — Terms of service - All pages render text content without authentication - Proper heading hierarchy - Footer links accessible from all public pages --- ### US-V03: 404 Not Found **As a** visitor, **I want to** see a helpful error page for invalid URLs, **So that** I can navigate back to valid content. **Acceptance Criteria:** - Custom 404 page with branded design - "Go Home" or navigation links - Displays on any non-existent route - Consistent with app theme (dark/light) --- ## Cross-Cutting: Non-Functional User Stories ### US-X01: Responsive Design **As any** user, **I want** the app to work on all device sizes, **So that** I can use it on mobile, tablet, or desktop. **Acceptance Criteria:** - Mobile (375px): Single column, hamburger menu, stacked cards - Tablet (768px): Sidebar collapses, 2-column where appropriate - Desktop (1280px): Full sidebar, multi-column layouts - No horizontal scrollbar at any breakpoint - Touch-friendly tap targets (≥44px) --- ### US-X02: Dark/Light Theme **As any** user, **I want** to switch between dark and light themes, **So that** I can use the app in my preferred color scheme. **Acceptance Criteria:** - Theme toggle accessible from settings/header - Dark mode: dark backgrounds, light text, green accents - Light mode: white backgrounds, dark text, green accents - Preference persisted in localStorage - System preference detection (prefers-color-scheme) - All pages render correctly in both modes --- ### US-X03: Internationalization (i18n) **As any** user, **I want** the app in German or English, **So that** I can use it in my preferred language. **Acceptance Criteria:** - German (de) as default language - English (en) as alternative - All UI labels, buttons, messages translated - Language switcher in settings - Date/number formatting adapts to locale - next-intl integration working --- ### US-X04: PWA & Offline Support **As any** user, **I want** the app to be installable and work offline, **So that** I can access it without constant connectivity. **Acceptance Criteria:** - Web app manifest with icons (192px, 512px) - Service worker registered - Offline page shows when no connectivity - Install prompt available on supported browsers - App icon on home screen after install --- ### US-X05: Accessibility (a11y) **As a** user with disabilities, **I want** the app to be accessible, **So that** I can use it with assistive technology. **Acceptance Criteria:** - All form inputs have associated labels - Proper heading hierarchy (h1 → h2 → h3) - Keyboard navigation works on all interactive elements - ARIA attributes on dynamic content - Color contrast meets WCAG 2.1 AA - Focus visible on interactive elements - Autocomplete attributes on login fields --- ### US-X06: Notifications **As an** admin, **I want to** receive real-time notifications, **So that** I'm alerted to important events. **Acceptance Criteria:** - Bell icon with unread count badge - Notification dropdown/panel - WebSocket (STOMP) real-time delivery - Notification types: low stock, quota warning, new member, system alert - Mark as read / mark all as read - Persistent across page navigation ---