# CannaManage — Wireframes & UI Mockups **Phase 4a | Document 6 of 7** **Date:** 2026-04-06 **Stack:** Spring Boot 3.x · React/Vite SPA · PostgreSQL --- ## Table of Contents 1. [Design System Overview](#1-design-system-overview) 2. [Admin Portal Screens](#2-admin-portal-screens) 3. [Member Portal Screens](#3-member-portal-screens) 4. [Navigation & Information Architecture](#4-navigation--information-architecture) 5. [Responsive Design Notes](#5-responsive-design-notes) 6. [Accessibility](#6-accessibility) --- ## 1. Design System Overview ### 1.1 Color Palette | Token | Hex | Usage | |---|---|---| | `--color-primary` | `#2D5016` | Sidebar background, primary buttons, active nav items | | `--color-primary-medium` | `#4A7C28` | Hover states, section headers, badge outlines | | `--color-accent` | `#8BC34A` | Highlights, progress bars filled, success indicators | | `--color-bg` | `#F5F5F5` | Page background, card backgrounds | | `--color-text` | `#1A1A1A` | Body text, table cell content | | `--color-warning` | `#FF6B35` | Quota >80%, low stock, warnings | | `--color-error` | `#D32F2F` | Quota exceeded, recalled batches, destructive actions | | `--color-white` | `#FFFFFF` | Sidebar text, button labels on dark bg, card surfaces | ### 1.2 Typography | Element | Font | Size | Weight | |---|---|---|---| | H1 — Page title | Inter | 24px | 600 | | H2 — Section heading | Inter | 18px | 600 | | H3 — Card title | Inter | 14px | 600 | | Body / table rows | Inter | 14px | 400 | | Caption / label | Inter | 12px | 400 | | Mono (codes, IDs) | JetBrains Mono | 13px | 400 | ### 1.3 Component Library The frontend is a **React/Vite SPA** with no PrimeFaces or JSF dependency. Component primitives come from [shadcn/ui](https://ui.shadcn.com/) (Radix UI + Tailwind CSS). This gives full control over styling, accessibility, and mobile responsiveness without JSF's lifecycle overhead. > **Why not PrimeFaces?** JSF/PrimeFaces is a server-side component model ill-suited to the modern REST API backend we're building. It tightly couples UI lifecycle to the backend, makes mobile responsiveness painful, and creates a hiring bottleneck. React is the right tool here. PrimeFaces is a fine choice for internal enterprise apps — not for a commercial SaaS. | Component | Library | Usage | |---|---|---| | `Card` / `Panel` | shadcn/ui | Section containers | | `DataTable` | TanStack Table v8 | Distributions, members, batches — virtualized | | `Pagination` | shadcn/ui Pagination | All tables | | `Input` | shadcn/ui Input | Single-line text fields | | `NumberInput` | react-number-format | Weight inputs (gram precision, min/max) | | `Select` | shadcn/ui Select | Dropdown selects (member, strain, batch) | | `DatePicker` | shadcn/ui Calendar | Date range pickers for reports | | `Progress` | shadcn/ui Progress | Quota consumption bar | | `Button` | shadcn/ui Button | Primary and secondary actions | | `AlertDialog` | shadcn/ui AlertDialog | Dangerous actions (recall) | | `Toast` | sonner | Success/error notifications | | `Badge` | shadcn/ui Badge | Status indicators (AVAILABLE, LOW, RECALLED) | | `Sheet` | shadcn/ui Sheet | Mobile nav drawer | | `Dialog` | shadcn/ui Dialog | Modal overlays | ### 1.4 Layout Grid ``` ┌────────────────────────────────────────────────────┐ │ TOP NAVBAR (56px) club name · avatar · logout │ ├──────────────┬─────────────────────────────────────┤ │ │ │ │ SIDEBAR │ MAIN CONTENT │ │ (240px) │ (fluid, min 784px) │ │ fixed │ │ │ │ │ └──────────────┴─────────────────────────────────────┘ ``` - **Sidebar:** fixed left, `#2D5016` background, white nav labels with `#8BC34A` icons - **Top Navbar:** `#FFFFFF` with bottom border `#E0E0E0`, breadcrumb left, user controls right - **Main Content:** `#F5F5F5` background, 24px padding, max content width 1200px centered --- ## 2. Admin Portal Screens ### Screen 1 — Admin Dashboard ![Admin Dashboard](images/mockup-admin-dashboard.png) #### ASCII Wireframe ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 🌿 CannaManage Grüne Oase Berlin e.V. 👤 Max M. [⏻] │ ├────────────┬────────────────────────────────────────────────────────┤ │ │ Dashboard 🗓 April 2026 │ │ 📊 Dashboard◄│ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ 👥 Members│ │ Total Members│ │ Distributions│ │ Stock Available│ │ │ │ │ │ │ This Month │ │ │ │ │ 📋 Distrib│ │ 142 │ │ 87 │ │ 3,240 g │ │ │ │ │ ▲ +3 MoM │ │ ▲ +12 MoM │ │ ▼ -800g MoM │ │ │ 📦 Stock │ └──────────────┘ └──────────────┘ └───────────────┘ │ │ │ │ │ 📄 Reports│ Recent Distributions [+ New Entry] │ │ │ ┌─────────────────────────────────────────────────┐ │ │ ✅ Complian│ │ Member │ Strain │ Qty │ Date │ ✓ │ │ │ │ ├─────────────┼─────────────┼───────┼───────┼────┤ │ │ ⚙ Settings│ │ Müller, A. │ OG Kush B12 │ 5.0g │ 06.04 │ ✓ │ │ │ │ │ Schmidt, K. │ Amnesia H09 │ 3.5g │ 06.04 │ ✓ │ │ │ │ │ Weber, T. │ OG Kush B12 │ 7.0g │ 05.04 │ ✓ │ │ │ │ │ … │ │ │ │ │ │ └────────────┴──┴─────────────────────────────────────────────────────┘ ``` #### Components & Behavior | Component | Library | Behavior | |---|---|---| | KPI Cards | shadcn/ui Card | Auto-refreshed via `useQuery` (react-query, 60s stale) | | Recent Distributions table | TanStack Table (5 rows) | Row click → navigate to distribution detail | | Member column link | React Router `` | Navigate to `/admin/members/{id}` | | `+ New Entry` button | shadcn/ui Button variant="default" | Navigate to `/admin/distributions/new` | | Trend indicators | Tailwind `text-green-600` / `text-red-600` | ▲/▼ with delta value | --- ### Screen 2 — Distribution Recording Form ![Distribution Form](images/mockup-distribution-form.png) #### ASCII Wireframe ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 🌿 CannaManage Grüne Oase Berlin e.V. 👤 Max M. [⏻] │ ├────────────┬────────────────────────────────────────────────────────┤ │ │ Distributions › New Distribution │ │ 📊 Dashbrd│ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ 👥 Members│ │ Member * │ │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ 📋 Distrib◄│ │ │ 🔍 Search by name or member no. │ │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ 📦 Stock │ │ │ │ │ │ │ Strain / Batch * │ │ │ 📄 Reports│ │ ┌──────────────────────────────────────────┐ │ │ │ │ │ │ Select available batch ▼ │ │ │ │ ✅ Complian│ │ └──────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ⚙ Settings│ │ Weight (grams) * │ │ │ │ │ ┌──────────┐ │ │ │ │ │ │ 0.0 g │ ← p:inputNumber min=0.1 max=25 │ │ │ │ │ └──────────┘ │ │ │ │ │ │ │ │ │ │ Monthly Quota — Müller, Anna │ │ │ │ │ ████████████░░░░░░░░ 32.5g / 50g 65% │ │ │ │ │ [████████████████░░░] <- p:progressBar │ │ │ │ │ │ │ │ │ │ [ Record Distribution ] [Cancel] │ │ │ │ └──────────────────────────────────────────────────┘ │ └────────────┴────────────────────────────────────────────────────────┘ ``` #### Compliance UX — Real-Time Quota Indicator The quota progress bar updates live as the weight field changes (via `f:ajax event="keyup"`): | Quota Used After Distribution | Bar Color | Submit Button | Message | |---|---|---|---| | 0–79% | `#8BC34A` (green) | Enabled | — | | 80–99% | `#FF6B35` (orange) | Enabled | "⚠ Approaching monthly limit" | | 100% | `#D32F2F` (red) | **Disabled** | "🚫 Monthly limit reached (50g)" | | Over-21 member, >30g monthly | `#D32F2F` (red) | **Disabled** | "🚫 Under-21 limit reached (30g)" | #### Components & Behavior | Component | Library | Behavior | |---|---|---| | Member search | shadcn/ui Combobox | `useQuery` debounced search; shows name + member no. | | Strain/Batch dropdown | shadcn/ui Select | Populated after member selection; filters `AVAILABLE` batches | | Weight input | react-number-format | min=0.1 max=25.0 step=0.1; triggers quota recalculation via `onChange` | | Quota bar | shadcn/ui Progress | Color class via `cn()` utility computed in component state | | Submit | shadcn/ui Button | `disabled={quotaExceeded}` from react state | | Cancel | React Router `` | Returns to distribution log without saving | --- ### Screen 3 — Stock Management ![Stock Management](images/mockup-stock-management.png) #### ASCII Wireframe ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 🌿 CannaManage Grüne Oase Berlin e.V. 👤 Max M. [⏻] │ ├────────────┬────────────────────────────────────────────────────────┤ │ │ Stock Management [+ Add Batch] │ │ 📊 Dashbrd│ │ │ │ ┌──────────────────────┐ ┌────────────────────┐ │ │ 👥 Members│ │ 🔍 Filter by strain │ │ Status: All ▼ │ │ │ │ └──────────────────────┘ └────────────────────┘ │ │ 📋 Distrib│ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ 📦 Stock ◄│ │ Strain │Batch│THC% │CBD%│ Qty │Status│Act │ │ │ │ ├──────────────┼─────┼─────┼────┼───────┼──────┼────┤ │ │ 📄 Reports│ │ OG Kush │B-12 │ 19% │ 1% │ 850g │ ● │[R] │ │ │ │ │ Amnesia Haze │H-09 │ 22% │<1% │ 72g │ ⚠ │[R] │ │ │ ✅ Complian│ │ Blue Dream │D-05 │ 17% │ 2% │ 0g │ — │[R] │ │ │ │ │ Hindu Kush │K-21 │ 8% │15% │ 340g │ ✓ │[R] │ │ │ ⚙ Settings│ │ AK-47 #4 │A-03 │ 20% │ 1% │ RECALLED │ ⛔ │[R] │ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ [◄ 1 2 3 … ►] Showing 1-10/42 │ └────────────┴────────────────────────────────────────────────────────┘ ``` #### Status Badges | Badge | Color | Icon | Condition | |---|---|---|---| | `AVAILABLE` | `#4A7C28` bg | ✓ checkmark | `qty > 100g` and not recalled | | `LOW` | `#FF6B35` bg | ⚠ warning | `0 < qty ≤ 100g` | | `EXHAUSTED` | `#9E9E9E` bg | — dash | `qty = 0` | | `RECALLED` | `#D32F2F` bg | ⛔ stop | `recall_date IS NOT NULL` | #### Components & Behavior | Component | Library | Behavior | |---|---|---| | Strain filter | shadcn/ui Input | Filters TanStack table client-side via `columnFilters` state | | Status filter | shadcn/ui Select | Filters table rows by status value | | Batch table | TanStack Table | Server-side pagination via `manualPagination`, 10 rows/page | | Status badge | shadcn/ui Badge variant mapped | Icon + text label (not color alone) | | Recall button | shadcn/ui Button variant="destructive" | Opens shadcn/ui AlertDialog before executing | | Confirm dialog | shadcn/ui AlertDialog | "Recall batch B-12 (OG Kush, 850g)? This cannot be undone." | | Add Batch | shadcn/ui Button | Opens shadcn/ui Dialog with batch entry form | --- ### Screen 4 — Compliance Report Generation ![Compliance Report](images/mockup-compliance-report.png) #### ASCII Wireframe ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 🌿 CannaManage Grüne Oase Berlin e.V. 👤 Max M. [⏻] │ ├────────────┬────────────────────────────────────────────────────────┤ │ │ Reports › Monthly Compliance Report │ │ 📊 Dashbrd│ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ 👥 Members│ │ Reporting Period │ │ │ │ │ Month: [ March ▼ ] Year: [ 2026 ▼ ] │ │ │ 📋 Distrib│ │ [ Generate Report ] │ │ │ │ └─────────────────────────────────────────────────┘ │ │ 📦 Stock │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ 📄 Reports◄│ │ PDF PREVIEW │ │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ ✅ Complian│ │ │ 🌿 CannaManage — Monthly Report Mar 2026 │ │ │ │ │ │ │ Club: Grüne Oase Berlin e.V. │ │ │ │ ⚙ Settings│ │ │ ─────────────────────────────────────── │ │ │ │ │ │ │ Total Members: 142 │ │ │ │ │ │ │ Active Members (distributed): 87 │ │ │ │ │ │ │ Total Distributed: 435.5g │ │ │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ [⬇ Download PDF] [⬇ Download CSV] │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ │ │ Summary Table │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ │ Metric │ Value │ Limit │ │ │ │ ├──────────────────────┼───────────┼─────────────┤ │ │ │ │ Members >50g/month │ 0 │ Must be 0 │ │ │ │ │ Members >30g (U21) │ 0 │ Must be 0 │ │ │ │ │ Recalled Batches │ 1 │ — (info) │ │ │ │ │ Avg grams / member │ 5.0g │ — │ │ │ │ └────────────────────────────────────────────────┘ │ └────────────┴────────────────────────────────────────────────────────┘ ``` #### Components & Behavior | Component | Library | Behavior | |---|---|---| | Month selector | shadcn/ui Select | Months Jan–Dec | | Year selector | shadcn/ui Select | Current year ± 2 | | Generate button | shadcn/ui Button | Calls report API; shows loading spinner; renders PDF thumbnail | | PDF preview | `