6.3 KiB
6.3 KiB
CLAUDE.md
Project Overview
Nextcloud 28 app (PHP backend, Vue 3 frontend) for managing scout group (Pfadfinderverein) members, families, fees, camps, and more.
Tech Stack
- Backend: PHP 8.1+, Nextcloud OCP APIs, MariaDB, Doctrine DBAL via
IDBConnection - Frontend: Vue 3 (Composition API,
<script setup>), Pinia stores, Vue Router (hash history),@nextcloud/vuev9, webpack - Build:
npx webpack --node-env production, output tojs/ - Deploy:
make redeploycopies app into running Nextcloud container. Version bump inappinfo/info.xmlrequired to bust browser cache (?v=hash).
Critical @nextcloud/vue v9 Gotchas
These caused most bugs in this project. Every contributor must know them:
- NcTextField: Use
:model-value/@update:model-value(Vue 3). NOT:value/@update:value/:value.sync(Vue 2). Fields will appear blank or not emit changes otherwise. - NcSelect: Always pass
:reduce="o => o.value"andlabel="label"when options are objects{value, label}. Without:reduce, the select can't match string model-values to option objects. - NcButton: Has
overflow: hiddenandpadding: 0in scoped styles. Global overrides via<style>blocks in.vuefiles are unreliable (css-loader may drop rules). Use a<style>tag injected frommain.jsafter mount instead. - appName/appVersion: The library reads these two ways: (a) bare global identifier
appName(use webpack DefinePlugin), (b) Vueinject('appName')(useapp.provide()). Both are needed. - loadState("core","apps"): Nextcloud 28 returns an object, not an array.
@nextcloud/vuecalls.find()on it, which crashes. Patch inmain.jswithObject.values()before Vue mounts.
Code Conventions
Vue Components
- Always use
<script setup>with Composition API - German UI labels with proper Umlauts (Wölflinge, Männlich, Zusätzliche Notizen, etc.)
- Validation: show errors inline during editing, disable submit button until valid
- Emit pattern for form components:
$emit('update', fieldName, value)— parent handles viaonFormUpdate(field, value)
Backend (PHP)
- Controllers extend
OCP\AppFramework\Controller, returnJSONResponse - Services handle business logic, Mappers handle DB queries (Nextcloud ORM pattern)
- Migrations in
lib/Migration/, class name formatVersionNNNNNNDateYYYYMMDDHHMMSS - Use
IQueryBuilder::PARAM_STRfor null values (notPARAM_NULLwhich doesn't exist) - Wire
AuditService->logCreate/logUpdate/logDeleteinto all CRUD service methods
Stores (Pinia)
- One store per entity (
stores/members.js,stores/families.js, etc.) - Fetch via
@nextcloud/axios+generateUrl() - Always expose
clearError()action
Testing
All PHPUnit tests must pass (make test) before merging. Runs inside the Nextcloud container — no local PHP needed. Zero errors, warnings, and PHP deprecations is the baseline for a commitable PR.
UI Guidelines
- Buttons must show full text, never truncated. Global fix in
main.jshandles NcButton overflow. - Sidebar active item must have rounded corners (global fix in
main.js). - Sensitive reports/actions use red styling (red border, red text) with tooltip explanation instead of overlapping badges.
- Use the global
SearchBarcomponent for member search, not inline NcTextField duplicates. - Tables should show all columns relevant to displayed filters (e.g. if "Geburtstage diesen Monat" filter exists, show Geburtsdatum column).
- Default sensible values for new records (e.g. Eintrittsdatum = today, Status = aktiv, Rolle = mitglied).
Deployment Notes
make deploy= full clean deploy (build + fresh containers + install NC + copy app + enable)make redeploy= rebuild JS + copy into running containermake clean=docker compose down -v(wipes DB + NC data volumes)- Always bump the version when redeploying UI changes. Without a version bump, Nextcloud serves cached JS/CSS and changes won't reach the browser — even with hard-refresh. Bump all three locations together.
When changes don't show up in the browser
This is a common problem. Nextcloud aggressively caches JS assets. Escalation path:
- Hard-refresh browser (Ctrl+Shift+R) — clears browser cache
- Restart container —
docker compose restart nextcloud— clears server-side opcache - Version bump — the reliable cache-buster. Must update in three places:
appinfo/info.xml(<version>)webpack.config.js(DefinePluginappVersion)main.js(app.provide('appVersion', ...)) Then runmake redeployfollowed byocc upgradeinside the container
- Full rebuild — nuclear option when nothing else works:
make clean && make deploy. This wipes all Docker volumes (DB included), rebuilds JS, starts fresh containers, reinstalls Nextcloud, and re-enables the app from scratch. You lose all data but guarantee a clean state.
Workflow
- Each completed feature, bugfix, or enhancement should be committed and pushed immediately after completion.
Gitea
- Repo:
shahondin1624/Mitgliederverwaltungongit.shahondin1624.de - Issues use labels:
enhancement,bug,backend,frontend,security,epic,priority:high/medium/low - Close issues via commit message:
(Closes #N)
Using tea CLI
Always use the tea CLI for Gitea operations (never the web UI or raw API calls):
# Pull requests
teaprclose<PR>
teaprclose<PR>
teapr create --head <branch> --title "<title>" --labels "<labels>" --description "<body>"
teapr list
teapr view <PR>
teapr diff <PR>
teapr merge <PR>
# Issues
tei list --state open
tei create --title "<title>" --labels "<labels>"
tei view <Issue>
tei close <Issue>
tei update <Issue> --labels "<new-labels>" --assignees "<user>"
# Labels
tel list
tel create <name> --color "<hex>" --description "<desc>"
# Milestones
tems list
tms create --title "<title>" --deadline "YYYY-MM-DD"
Rules:
- Before creating a PR: ensure the branch is pushed to origin first, and verify there are actual commits on the branch (never create a PR from a branch identical to main/base)
- Always use
tea pr diffto verify the PR has the expected changes before merging - Use
tea pr mergeto merge after review - Close issues via commit message
(Closes #N)—teais only for PR/issue management on the Gitea server