# 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

---
