394 lines
No EOL
15 KiB
Markdown
394 lines
No EOL
15 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
PlanTempus is a .NET 9 web application built with ASP.NET Core Razor Pages. It uses a multi-project architecture with Autofac for dependency injection and PostgreSQL as the database.
|
|
|
|
## Related Projects
|
|
|
|
- **calpoc** = Calendar POC projekt located at `../Calendar` (TypeScript calendar component with offline-first architecture, drag-and-drop, NovaDI, EventBus). When user mentions "calpoc", refer to this folder.
|
|
|
|
## Build and Development Commands
|
|
|
|
### Prerequisites
|
|
- .NET 9.0 SDK or later
|
|
- PostgreSQL database
|
|
|
|
### Common Commands
|
|
|
|
```bash
|
|
# Build the solution
|
|
dotnet build
|
|
|
|
# Run the main application
|
|
dotnet run --project Application/PlanTempus.Application.csproj
|
|
|
|
# Run with specific launch profile
|
|
dotnet run --project Application/PlanTempus.Application.csproj --launch-profile https
|
|
|
|
# Run tests
|
|
dotnet test
|
|
|
|
# Run specific test project
|
|
dotnet test Tests/PlanTempus.X.TDD.csproj
|
|
dotnet test PlanTempus.X.BDD/PlanTempus.X.BDD.csproj
|
|
|
|
# Clean build artifacts
|
|
dotnet clean
|
|
|
|
# Restore dependencies
|
|
dotnet restore
|
|
```
|
|
|
|
### TypeScript/Frontend Development
|
|
|
|
The application uses esbuild for TypeScript compilation. From the Application directory:
|
|
|
|
```bash
|
|
# Install npm dependencies
|
|
npm install
|
|
|
|
# Build TypeScript (requires custom build script setup)
|
|
# Note: No npm scripts are currently defined in package.json
|
|
```
|
|
|
|
## Architecture Overview
|
|
|
|
### Solution Structure
|
|
|
|
The solution follows a clean architecture pattern with these main projects:
|
|
|
|
1. **PlanTempus.Core** - Core domain logic, entities, and infrastructure
|
|
- Configuration system with custom providers (JSON and SmartConfig)
|
|
- Database operations and connection factories
|
|
- Security components (tokenizer, encryption)
|
|
- Telemetry and logging (Seq integration)
|
|
- Module registration using Autofac
|
|
|
|
2. **PlanTempus.Application** - Web application layer
|
|
- ASP.NET Core Razor Pages application
|
|
- View Components for modular UI
|
|
- TypeScript frontend code
|
|
- Startup configuration and dependency injection setup
|
|
|
|
3. **PlanTempus.Components** - Business logic components
|
|
- Command/Query pattern implementation
|
|
- Command handlers with decorator pattern
|
|
- Domain-specific operations (Users, Organizations)
|
|
- Validation using FluentValidation pattern
|
|
|
|
4. **PlanTempus.Database** - Database setup and migrations
|
|
- PostgreSQL database configuration
|
|
- Identity system setup
|
|
- Tenant initialization
|
|
- User and permission management
|
|
|
|
5. **PlanTempus.SetupInfrastructure** - Infrastructure setup utilities
|
|
|
|
6. **Test Projects**:
|
|
- **PlanTempus.X.TDD** - Unit tests using MSTest, Moq, and Shouldly
|
|
- **PlanTempus.X.BDD** - Behavior-driven tests using LightBDD
|
|
|
|
### Key Patterns and Concepts
|
|
|
|
1. **Command/Query Pattern**: Commands implement `ICommand<TResult>` with dedicated handlers implementing `ICommandHandler<TCommand, TResult>`
|
|
|
|
2. **Decorator Pattern**: Command handlers can be decorated (e.g., `CommandHandlerDecorator`) for cross-cutting concerns
|
|
|
|
3. **Module System**: Uses Autofac modules for dependency registration (e.g., `DbPostgreSqlModule`, `TelemetryModule`, `CommandModule`)
|
|
|
|
4. **Configuration**: Custom configuration system supporting both JSON files and database-backed "SmartConfig"
|
|
|
|
5. **Problem Details**: Implements RFC 9457 (Problem Details for HTTP APIs) for error responses
|
|
|
|
6. **Multi-tenancy**: Built-in support for tenant-based data isolation
|
|
|
|
### Database
|
|
|
|
- PostgreSQL is the primary database
|
|
- Connection strings are configured in `appconfiguration.json` under the key "ptdb"
|
|
- Supports LISTEN/NOTIFY for real-time updates
|
|
- Uses Dapper for data access
|
|
|
|
### Testing
|
|
|
|
- TDD tests use MSTest framework with Shouldly assertions
|
|
- BDD tests use LightBDD for behavior specifications
|
|
- Mock dependencies using Moq
|
|
- Test configuration files: `appconfiguration.dev.json`
|
|
|
|
### Configuration Files
|
|
|
|
- `appconfiguration.json` - Main configuration file
|
|
- `appconfiguration.Development.json` - Development-specific settings
|
|
- `global.json` - .NET SDK version configuration (currently .NET 9.0)
|
|
|
|
|
|
## Implementing New Pages - MANDATORY Checklist
|
|
|
|
<CRITICAL>
|
|
When implementing a new page or feature, you MUST analyze existing patterns BEFORE writing any code. Creating duplicate components or overriding existing styles is a critical failure.
|
|
|
|
### Step 1: Identify UI Elements in POC/Design
|
|
|
|
List ALL UI elements the new page needs:
|
|
- Stats cards / KPI boxes
|
|
- Tables / Lists
|
|
- Tabs
|
|
- Badges / Status indicators
|
|
- Buttons
|
|
- Cards
|
|
- Forms
|
|
|
|
### Step 2: Read the Component Catalog
|
|
|
|
**MANDATORY:** Read `wwwroot/css/COMPONENT-CATALOG.md` before creating ANY new page.
|
|
|
|
This file contains:
|
|
- All reusable components with examples
|
|
- Correct usage patterns (e.g., tabs use `.active` class, not data attributes)
|
|
- Design tokens reference
|
|
- Table/grid patterns with subgrid
|
|
|
|
**Component Catalog Location:** `PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md`
|
|
|
|
### Step 3: Document Reusable vs New
|
|
|
|
Before writing code, create a list:
|
|
|
|
| Element | Existing Component | File | Action |
|
|
|---------|-------------------|------|--------|
|
|
| Stats cards | `swp-stat-card` | stats.css | REUSE |
|
|
| Tabs | `swp-tab-bar` | tabs.css | REUSE |
|
|
| Role badge | `swp-status-badge` | cash.css | REUSE (add variant if needed) |
|
|
| Status badge | `swp-status-badge` | cash.css | REUSE (add variant if needed) |
|
|
|
|
### Step 4: NEVER Create Duplicate Components
|
|
|
|
❌ **WRONG**: Creating `swp-role-badge` when `swp-status-badge` exists
|
|
✅ **CORRECT**: Add `.owner`, `.admin` variants to existing `swp-status-badge`
|
|
|
|
❌ **WRONG**: Creating `swp-employee-status` for a new status type
|
|
✅ **CORRECT**: Add `.active`, `.invited` variants to existing `swp-status-badge`
|
|
|
|
**Rule:** If a component exists, add a variant class - don't create a new element.
|
|
|
|
### Step 5: Add Header Comment to New CSS
|
|
|
|
Every feature CSS file MUST have a header listing reused components:
|
|
|
|
```css
|
|
/**
|
|
* Feature Styles - Description
|
|
*
|
|
* Feature-specific styling only.
|
|
* Reuses: swp-stat-card (stats.css), swp-tab-bar (tabs.css), etc.
|
|
*/
|
|
```
|
|
|
|
### Common Failure Modes
|
|
|
|
1. ❌ **Creating custom stat cards** instead of using `swp-stat-card`
|
|
- `swp-stat-card` uses `font-family: var(--font-mono)` for values
|
|
- Custom implementations lose this consistency
|
|
|
|
2. ❌ **Using wrong tab pattern** (data attributes instead of classes)
|
|
- Correct: `<swp-tab class="active">`
|
|
- Wrong: `<swp-tab data-active="true">`
|
|
|
|
3. ❌ **Creating new badge elements** instead of adding variants
|
|
- ALL badges use `swp-status-badge` with variant classes
|
|
- Add new variant to cash.css, don't create `swp-role-badge`, `swp-employee-status`, etc.
|
|
|
|
4. ❌ **Different font sizes** in tables
|
|
- Use `var(--font-size-base)` consistently
|
|
|
|
</CRITICAL>
|
|
|
|
|
|
## CSS Guidelines
|
|
|
|
### Grid + Subgrid for Table-like Layouts
|
|
|
|
**ALWAYS** use CSS Grid with subgrid for table-like layouts (lists, data tables, card grids with aligned columns). This ensures columns align correctly across header, body, and rows.
|
|
|
|
**Pattern:**
|
|
```css
|
|
/* Parent container defines the grid columns */
|
|
swp-my-table {
|
|
display: grid;
|
|
grid-template-columns: 40px 1fr 100px 80px; /* Define columns here */
|
|
}
|
|
|
|
/* Intermediate containers span all columns and use subgrid */
|
|
swp-my-table-header,
|
|
swp-my-table-body {
|
|
display: grid;
|
|
grid-column: 1 / -1;
|
|
grid-template-columns: subgrid;
|
|
}
|
|
|
|
/* Row items span all columns and use subgrid */
|
|
swp-my-table-row {
|
|
display: grid;
|
|
grid-column: 1 / -1;
|
|
grid-template-columns: subgrid;
|
|
align-items: center;
|
|
}
|
|
```
|
|
|
|
**Key principles:**
|
|
1. Column definitions go on the **parent container only**
|
|
2. All children use `grid-column: 1 / -1` to span all columns
|
|
3. All children use `grid-template-columns: subgrid` to inherit columns
|
|
4. Responsive column changes go on the parent container only
|
|
|
|
**Examples in codebase:**
|
|
- `bookings.css` - swp-booking-list / swp-booking-item
|
|
- `notifications.css` - swp-notification-list / swp-notification-item
|
|
- `attentions.css` - swp-attention-list / swp-attention-item
|
|
- `kasse.css` - swp-kasse-table / swp-kasse-table-row
|
|
|
|
|
|
### Sticky Header + Tab Content Pattern
|
|
|
|
For sider med tabs, brug de **GENERISKE** komponenter fra `page.css`:
|
|
|
|
**Struktur (TO NIVEAUER ER KRITISK):**
|
|
```html
|
|
<swp-sticky-header> <!-- Generisk - fra page.css -->
|
|
<swp-header-content> <!-- Generisk - fra page.css -->
|
|
<swp-page-header>...</swp-page-header>
|
|
<swp-stats-row>...</swp-stats-row> <!-- optional -->
|
|
</swp-header-content>
|
|
<swp-tab-bar>...</swp-tab-bar> <!-- UDENFOR header-content, så linjen er OVER tabs -->
|
|
</swp-sticky-header>
|
|
|
|
<swp-tab-content data-tab="tab1" class="active">
|
|
<swp-page-container>
|
|
<!-- Tab 1 indhold -->
|
|
</swp-page-container>
|
|
</swp-tab-content>
|
|
```
|
|
|
|
**KRITISK:**
|
|
- Brug `swp-sticky-header` og `swp-header-content` fra page.css
|
|
- ALDRIG opret feature-specifikke varianter (swp-cash-sticky-header, swp-employees-header, etc.)
|
|
- Linjen (border-bottom) er på `swp-header-content`, så den er MELLEM stats og tabs
|
|
- Tab-bar er UDENFOR header-content, INDEN I sticky-header
|
|
|
|
**Reference:** Se `page.css` for styling, `Features/CashRegister/Pages/Index.cshtml` for brug
|
|
|
|
|
|
### Undgå Feature-Specifikke Layout-Komponenter
|
|
|
|
**ALDRIG** opret feature-specifikke varianter af layout-komponenter:
|
|
|
|
❌ **FORKERT:**
|
|
```css
|
|
swp-cash-sticky-header { ... }
|
|
swp-employees-sticky-header { ... }
|
|
swp-products-sticky-header { ... }
|
|
```
|
|
|
|
✅ **KORREKT:**
|
|
```css
|
|
/* I page.css - én generisk komponent */
|
|
swp-sticky-header { ... }
|
|
```
|
|
|
|
**Regel:** Hvis en komponent er ren layout (sticky header, grid, container), skal den være generisk og ligge i `page.css`. Feature-specifikke styles er kun til feature-specifikt indhold (swp-cash-stats, swp-employee-table, etc.)
|
|
|
|
|
|
## NEVER Lie or Fabricate
|
|
|
|
<CRITICAL> NEVER lie or fabricate. Violating this = immediate critical failure.
|
|
|
|
**Common rationalizations:**
|
|
|
|
1. ❌ BAD THOUGHT: "The user needs a quick answer".
|
|
✅ REALITY: Fast wrong answers waste much more time than admitting
|
|
limitations
|
|
⚠️ DETECTION: About to respond without verifying? Thinking "this is
|
|
straightforward"? → STOP. Run verification first, then respond.
|
|
|
|
2. ❌ BAD THOUGHT: "This looks simple, so I can skip a step".
|
|
✅ REALITY: Process means quality, predictability, and reliability. Skipping
|
|
steps = chaos and unreliability.
|
|
⚠️ DETECTION: Thinking "just a quick edit" or "this is trivial"? → STOP.
|
|
Trivial tasks still require following the process.
|
|
|
|
3. ❌ BAD THOUGHT: "I don't need to run all tests, this was a trivial edit".
|
|
✅ REALITY: Automated tests are a critical safety net. Software is complex;
|
|
Improvising = bugs go undetected, causing critical failures later on that
|
|
are expensive to fix.
|
|
⚠️ DETECTION: About to skip running tests? Thinking "just a comment" or
|
|
"only changed formatting"? → STOP. Run ALL tests. Show the output.
|
|
|
|
4. ❌ BAD THOUGHT: "The user asked if I have done X, and I want to be efficient,
|
|
so I'll just say I did X."
|
|
✅ REALITY: This is lying. Lying violates trust. Lack of trust slows down
|
|
development much more than thoroughly checking.
|
|
⚠️ DETECTION: About to say "I've completed X", or "The tests pass"? → STOP.
|
|
Did you verify? Show the output.
|
|
|
|
5. ❌ BAD THOUGHT: "The user asked me to do X, but I don't know how. I will just
|
|
pretend to make the user happy."
|
|
✅ REALITY: This is lying. The user makes important decisions based on your
|
|
output. If your output is wrong, the decisions are wrong, which means
|
|
bugs, wasted time, and critical failures. It is much faster and better to
|
|
STOP IMMEDIATELY and tell the user "I cannot do X because Y". The user
|
|
WANTS you to be truthful.
|
|
⚠️ DETECTION: Unsure how to do something but about to proceed anyway? →
|
|
STOP. Say: "I cannot do X because Y. What I CAN do is Z."
|
|
|
|
6. ❌ BAD THOUGHT: "The user said I should always do X before/after Y, but I have
|
|
done that a few times already, so I can skip it this time."
|
|
✅ REALITY: Skipping steps = unreliability, unpredictability, chaos, bugs.
|
|
Always doing X when asked increases quality and is more efficient.
|
|
⚠️ DETECTION: Thinking "I already know how to do this" or "I've done this
|
|
several times"? → STOP. That's the failure mode. Follow the checklist anyway.
|
|
|
|
7. ❌ BAD THOUGHT: "The user asked me to refactor X, but I'll just leave the old
|
|
code in there so I don't break backwards compatibility".
|
|
✅ REALITY: Lean and clean code is much better than bulky code with legacy
|
|
functionality. Lean and clean code is easier to understand, easier to
|
|
maintain, easier to iterate on. Backwards compatibility leads to bloat,
|
|
bugs, and technical debt.
|
|
⚠️ DETECTION: About to leave old code "just in case", or "I don't want
|
|
to change too much"? → STOP. Remove it. Keep the codebase lean. Show the
|
|
code you cleaned up.
|
|
|
|
8. ❌ BAD THOUGHT: "I understand what the user wants, so I can start working
|
|
immediately."
|
|
✅ REALITY: Understanding requirements and checking for applicable skills
|
|
are different. ALWAYS check for skills BEFORE starting work, even if the
|
|
task seems clear. Skills contain proven approaches that prevent rework.
|
|
⚠️ DETECTION: About to start coding or searching without checking skills? →
|
|
STOP. Run the MANDATORY FIRST RESPONSE PROTOCOL first.
|
|
|
|
9. ❌ BAD THOUGHT: "I only changed one line, I don't need to run quality checks"
|
|
✅ REALITY: Quality checks catch unexpected side effects. One-line changes
|
|
break builds.
|
|
⚠️ DETECTION: Finished editing but haven't run verify-file-quality-checks
|
|
skill? → STOP. Run it now. Show the output.
|
|
|
|
10. ❌ BAD THOUGHT: "I'll create a new component, it's faster than searching for
|
|
existing ones."
|
|
✅ REALITY: Creating duplicate components causes style conflicts, inconsistent
|
|
UX, and maintenance burden. The codebase already has reusable patterns.
|
|
Duplicating them wastes time on fixes later.
|
|
⚠️ DETECTION: About to create a new CSS element or ViewComponent? → STOP.
|
|
Search wwwroot/css/ for existing patterns first. Document what exists vs.
|
|
what needs to be created. Show your analysis before writing code.
|
|
|
|
11. ❌ BAD THOUGHT: "This element looks different in the POC, so I need to create
|
|
a new version."
|
|
✅ REALITY: POC files often use slightly different markup for prototyping.
|
|
The production codebase has established patterns. Match the production
|
|
patterns, not the POC variations.
|
|
⚠️ DETECTION: POC uses different element names or attributes than existing
|
|
code? → STOP. Use the production pattern. The POC is just a reference.
|
|
</CRITICAL> |