chore: full technical rename planarchy → capakraken

Complete rename of all technical identifiers across the codebase:

Package names (11 packages):
- @planarchy/* → @capakraken/* in all package.json, tsconfig, imports

Import statements: 277 files, 548 occurrences replaced

Database & Docker:
- PostgreSQL user/db: planarchy → capakraken
- Docker volumes: planarchy_pgdata → capakraken_pgdata
- Connection strings updated in docker-compose, .env, CI

CI/CD:
- GitHub Actions workflow: all filter commands updated
- Test database credentials updated

Infrastructure:
- Redis channel: planarchy:sse → capakraken:sse
- Logger service name: planarchy-api → capakraken-api
- Anonymization seed updated
- Start/stop/restart scripts updated

Test data:
- Seed emails: @planarchy.dev → @capakraken.dev
- E2E test credentials: all 11 spec files updated
- Email defaults: @planarchy.app → @capakraken.app
- localStorage keys: planarchy_* → capakraken_*

Documentation: 30+ .md files updated

Verification:
- pnpm install: workspace resolution works
- TypeScript: only pre-existing TS2589 (no new errors)
- Engine: 310/310 tests pass
- Staffing: 37/37 tests pass

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-03-27 13:18:09 +01:00
parent f46b38f457
commit cd78f72f33
303 changed files with 938 additions and 878 deletions
+1 -1
View File
@@ -436,7 +436,7 @@ The agent operates within the Planarchy monorepo and must adhere to all engineer
- **tRPC:** New routers must be registered in `packages/api/src/router/index.ts`
- **TypeScript:** `exactOptionalPropertyTypes: true` — use spread pattern, never assign `undefined`
- **No speculative abstractions** — only build what the ticket requires
- **Quality gates:** `pnpm test:unit`, `pnpm --filter @planarchy/web exec tsc --noEmit`, `pnpm lint`
- **Quality gates:** `pnpm test:unit`, `pnpm --filter @capakraken/web exec tsc --noEmit`, `pnpm lint`
## Arguments
+5 -5
View File
@@ -7,7 +7,7 @@ Lies `plan.md` und implementiere die Tasks Schritt für Schritt. Führe nach jed
- Monorepo: pnpm workspaces + Turborepo
- Stack: Next.js 15 App Router + tRPC v11 + Prisma + PostgreSQL
- Dev-Server: `pnpm dev` auf Port 3100
- DB: PostgreSQL auf Port 5433 (`postgresql://planarchy:planarchy_dev@localhost:5433/planarchy`)
- DB: PostgreSQL auf Port 5433 (`postgresql://planarchy:capakraken_dev@localhost:5433/planarchy`)
## Implementierungs-Reihenfolge (immer einhalten)
1. **Prisma Schema** (`packages/db/prisma/schema.prisma`) → `pnpm db:push`
@@ -18,14 +18,14 @@ Lies `plan.md` und implementiere die Tasks Schritt für Schritt. Führe nach jed
## Nach jeder Schema-Änderung (Pflicht!)
```bash
DATABASE_URL="postgresql://planarchy:planarchy_dev@localhost:5433/planarchy" \
pnpm --filter @planarchy/db exec prisma generate
DATABASE_URL="postgresql://planarchy:capakraken_dev@localhost:5433/planarchy" \
pnpm --filter @capakraken/db exec prisma generate
rm -rf apps/web/.next
```
## Quality Gate nach jedem Task
```bash
pnpm --filter @planarchy/web exec tsc --noEmit 2>&1 | grep -v "BlueprintFieldEditor"
pnpm --filter @capakraken/web exec tsc --noEmit 2>&1 | grep -v "BlueprintFieldEditor"
# BlueprintFieldEditor TS2589 ist ein bekannter Pre-existing-Error, kein neuer Fehler
```
@@ -47,6 +47,6 @@ refactor: [refactoring-beschreibung]
## Abschluss
Wenn alle Tasks erledigt:
1. `pnpm test:unit` alle Tests grün?
2. `pnpm --filter @planarchy/web exec tsc --noEmit` sauber?
2. `pnpm --filter @capakraken/web exec tsc --noEmit` sauber?
3. Learning in `LEARNINGS.md` eintragen
4. `git commit -m "docs: learning erfasst - [kurzbeschreibung]"`
+1 -1
View File
@@ -113,7 +113,7 @@ Erstelle `research/perf-audit-[datum].md`:
2. Lies alle tRPC Router in `packages/api/src/router/`
3. Prüfe alle `useQuery`-Aufrufe in `apps/web/src/` auf staleTime und placeholderData
4. Führe PostgreSQL `EXPLAIN ANALYZE` auf die wichtigsten Queries aus
5. Prüfe Bundle-Größen via `pnpm --filter @planarchy/web build` (optional)
5. Prüfe Bundle-Größen via `pnpm --filter @capakraken/web build` (optional)
6. Erstelle priorisierten Befundbericht
Beginne sofort mit Layer 1 (Datenbank) und arbeite dich durch alle Layer.
+1 -1
View File
@@ -32,7 +32,7 @@ Analysiere die gegebene Anforderung und erstelle einen konkreten Umsetzungsplan.
### Akzeptanzkriterien
- [ ] `pnpm test:unit` läuft grün
- [ ] `pnpm --filter @planarchy/web exec tsc --noEmit` keine neuen Errors
- [ ] `pnpm --filter @capakraken/web exec tsc --noEmit` keine neuen Errors
- [ ] [Feature-spezifische Kriterien]
### Risiken & offene Fragen
+1 -1
View File
@@ -18,7 +18,7 @@ pnpm test:unit
### 2. TypeScript
```bash
pnpm --filter @planarchy/web exec tsc --noEmit 2>&1
pnpm --filter @capakraken/web exec tsc --noEmit 2>&1
# Bekannter Pre-existing-Error: BlueprintFieldEditor.tsx TS2589 → ignorieren
# Alle anderen Errors müssen 0 sein
```
+25 -25
View File
@@ -37,7 +37,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @planarchy/db exec prisma generate
run: pnpm --filter @capakraken/db exec prisma generate
- name: Cache Turborepo
uses: actions/cache@v4
@@ -47,7 +47,7 @@ jobs:
restore-keys: turbo-typecheck-
- name: Run typecheck
run: pnpm --filter @planarchy/web exec tsc --noEmit
run: pnpm --filter @capakraken/web exec tsc --noEmit
# ──────────────────────────────────────────────
# Lint — ~20s, no services needed
@@ -71,7 +71,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @planarchy/db exec prisma generate
run: pnpm --filter @capakraken/db exec prisma generate
- name: Cache Turborepo
uses: actions/cache@v4
@@ -93,13 +93,13 @@ jobs:
postgres:
image: postgres:16
env:
POSTGRES_DB: planarchy_test
POSTGRES_USER: planarchy
POSTGRES_PASSWORD: planarchy_test
POSTGRES_DB: capakraken_test
POSTGRES_USER: capakraken
POSTGRES_PASSWORD: capakraken_test
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U planarchy -d planarchy_test"
--health-cmd="pg_isready -U capakraken -d capakraken_test"
--health-interval=10s
--health-timeout=5s
--health-retries=5
@@ -113,7 +113,7 @@ jobs:
--health-timeout=5s
--health-retries=5
env:
DATABASE_URL: postgresql://planarchy:planarchy_test@localhost:5432/planarchy_test
DATABASE_URL: postgresql://capakraken:capakraken_test@localhost:5432/capakraken_test
REDIS_URL: redis://localhost:6379
steps:
- uses: actions/checkout@v4
@@ -131,16 +131,16 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @planarchy/db exec prisma generate
run: pnpm --filter @capakraken/db exec prisma generate
- name: Run unit tests with coverage
run: |
pnpm --filter @planarchy/engine exec vitest run --coverage
pnpm --filter @planarchy/staffing exec vitest run --coverage
pnpm --filter @planarchy/api exec vitest run --coverage
pnpm --filter @planarchy/application exec vitest run --coverage
pnpm --filter @planarchy/shared exec vitest run --coverage
pnpm --filter @planarchy/db test:unit
pnpm --filter @capakraken/engine exec vitest run --coverage
pnpm --filter @capakraken/staffing exec vitest run --coverage
pnpm --filter @capakraken/api exec vitest run --coverage
pnpm --filter @capakraken/application exec vitest run --coverage
pnpm --filter @capakraken/shared exec vitest run --coverage
pnpm --filter @capakraken/db test:unit
# ──────────────────────────────────────────────
# Build — depends on typecheck passing
@@ -167,7 +167,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @planarchy/db exec prisma generate
run: pnpm --filter @capakraken/db exec prisma generate
- name: Cache Turborepo
uses: actions/cache@v4
@@ -184,7 +184,7 @@ jobs:
restore-keys: nextjs-${{ hashFiles('pnpm-lock.yaml') }}-
- name: Build
run: pnpm --filter @planarchy/web exec next build
run: pnpm --filter @capakraken/web exec next build
# ──────────────────────────────────────────────
# E2E — depends on build, needs PostgreSQL + Redis
@@ -197,13 +197,13 @@ jobs:
postgres:
image: postgres:16
env:
POSTGRES_DB: planarchy_test
POSTGRES_USER: planarchy
POSTGRES_PASSWORD: planarchy_test
POSTGRES_DB: capakraken_test
POSTGRES_USER: capakraken
POSTGRES_PASSWORD: capakraken_test
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U planarchy -d planarchy_test"
--health-cmd="pg_isready -U capakraken -d capakraken_test"
--health-interval=10s
--health-timeout=5s
--health-retries=5
@@ -217,7 +217,7 @@ jobs:
--health-timeout=5s
--health-retries=5
env:
DATABASE_URL: postgresql://planarchy:planarchy_test@localhost:5432/planarchy_test
DATABASE_URL: postgresql://capakraken:capakraken_test@localhost:5432/capakraken_test
REDIS_URL: redis://localhost:6379
PORT: 3100
steps:
@@ -236,7 +236,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @planarchy/db exec prisma generate
run: pnpm --filter @capakraken/db exec prisma generate
- name: Cache Playwright browsers
id: playwright-cache
@@ -248,11 +248,11 @@ jobs:
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm --filter @planarchy/web exec playwright install --with-deps chromium
run: pnpm --filter @capakraken/web exec playwright install --with-deps chromium
- name: Install Playwright system deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: pnpm --filter @planarchy/web exec playwright install-deps chromium
run: pnpm --filter @capakraken/web exec playwright install-deps chromium
- name: Push DB schema & seed
run: |
+3 -3
View File
@@ -1,8 +1,8 @@
# Planarchy
# CapaKraken
## Ziel
Planarchy ist ein Ressourcenplanungs- und Projektbesetzungs-Tool fuer eine 3D-Produktionsumgebung. Der aktuelle Produktkern umfasst Timeline-Planung, Kapazitaets- und Budgetsicht, Rollenmanagement, Blueprint-basierte dynamische Felder, Skill-Matrix-Workflows und einen AI-unterstuetzten Staffing-/Profilbereich.
CapaKraken ist ein Ressourcenplanungs- und Projektbesetzungs-Tool fuer eine 3D-Produktionsumgebung. Der aktuelle Produktkern umfasst Timeline-Planung, Kapazitaets- und Budgetsicht, Rollenmanagement, Blueprint-basierte dynamische Felder, Skill-Matrix-Workflows und einen AI-unterstuetzten Staffing-/Profilbereich.
## Tech Stack
@@ -41,7 +41,7 @@ planarchy/
## Quality Gates
- `pnpm test:unit`
- `pnpm --filter @planarchy/web exec tsc --noEmit`
- `pnpm --filter @capakraken/web exec tsc --noEmit`
- `pnpm lint`
## Dokumente
+6 -6
View File
@@ -27,7 +27,7 @@
### 2026-03-11 | Architecture | Phase 1: Application Layer Extraction
- Created `packages/application` with `createAllocation` and `fillPlaceholder` use-case services
- `packages/api` router procedures now delegate to use cases; they only check permissions and emit SSE events
- `packages/application` depends on `@planarchy/db`, `@planarchy/engine`, `@planarchy/shared`; `packages/api` depends on `@planarchy/application`
- `packages/application` depends on `@capakraken/db`, `@capakraken/engine`, `@capakraken/shared`; `packages/api` depends on `@capakraken/application`
- Use cases throw `TRPCError` directly (pragmatic — project only uses tRPC transport)
- `Prisma.AllocationGetPayload<{ include: ... }>` used for precise return type in use cases
- `exactOptionalPropertyTypes` + optional params: caller must use spread `...(val !== undefined ? { key: val } : {})` when passing zod inputs to use cases with `{ key?: T }` interfaces
@@ -43,7 +43,7 @@
### 2026-03-12 | Architecture | Estimating foundation slice
- Added first-class Prisma estimating models for `Estimate`, `EstimateVersion`, assumptions, scope items, demand lines, rate cards, resource snapshots, metrics, and exports.
- Keep this slice deliberately narrow: persistence + shared contracts + application/engine boundaries first, before any wizard/workspace UI. That avoids baking spreadsheet-shaped UI assumptions into the domain model.
- Shared estimate enums/types/schemas now live in `@planarchy/shared`, and initial application commands/queries (`createEstimate`, `listEstimates`, `getEstimateById`) live in `@planarchy/application`.
- Shared estimate enums/types/schemas now live in `@capakraken/shared`, and initial application commands/queries (`createEstimate`, `listEstimates`, `getEstimateById`) live in `@capakraken/application`.
- Added a small engine contract `summarizeEstimateDemandLines()` for aggregate financial totals so later estimate work can reuse a typed pure-function boundary instead of recomputing ad hoc in routers/components.
### 2026-03-11 | Architecture | Tasks 23-27: Bulk Edit, Validation, Export, Reorder
@@ -61,10 +61,10 @@
- `useSearchParams` requires `<Suspense>` wrapping at the page level in Next.js App Router or the page will be statically rendered without search param access.
### 2026-03-11 | Security | Phase 0 critical fixes
- `user.create` was hashing passwords with SHA-256; `auth.ts` verifies with Argon2 → users created via admin couldn't log in. Fix: import `hash` from `@node-rs/argon2` in the router. Must also declare `@node-rs/argon2` in `packages/api/package.json` — being a dep of `@planarchy/db` is not enough for TS resolution.
- `user.create` was hashing passwords with SHA-256; `auth.ts` verifies with Argon2 → users created via admin couldn't log in. Fix: import `hash` from `@node-rs/argon2` in the router. Must also declare `@node-rs/argon2` in `packages/api/package.json` — being a dep of `@capakraken/db` is not enough for TS resolution.
- `notification.create` was `protectedProcedure` → any logged-in user could create notifications for arbitrary users. Fix: changed to `managerProcedure`.
- `testAiConnection` always built Azure deployment URLs regardless of `aiProvider`. Fix: branch on provider, use `https://api.openai.com/v1/chat/completions` with `Authorization: Bearer` for OpenAI.
- `@planarchy/shared` had `test:unit: vitest run` in package.json but no test files → turbo failed. Fix: remove the script (tests live only in engine/staffing).
- `@capakraken/shared` had `test:unit: vitest run` in package.json but no test files → turbo failed. Fix: remove the script (tests live only in engine/staffing).
- `crypto.randomUUID()` in `packages/shared/src/schemas/project.schema.ts` failed typecheck because base tsconfig uses `"lib": ["ES2022"]` without DOM. Fix: add `"lib": ["ES2022", "DOM"]` in the shared package's own tsconfig.
### 2026-03-09 | Performance | Budget utilization showing 562% due to wrong aggregation
@@ -149,7 +149,7 @@ For modal focus trapping: create a `panelRef = useRef<HTMLDivElement>(null)`, ca
---
### 2026-02-xx | Architektur | Prisma-Enum vs. Shared-Enum
**Problem:** Prisma generiert eigene Enum-Typen, die TypeScript-seitig nicht mit den `@planarchy/shared`-Enums kompatibel sind.
**Problem:** Prisma generiert eigene Enum-Typen, die TypeScript-seitig nicht mit den `@capakraken/shared`-Enums kompatibel sind.
**Lösung:** An Client-Grenzen `as unknown as SharedType` casten:
- `project as unknown as Project`
- `form.orderType as unknown as OrderType`
@@ -181,7 +181,7 @@ For modal focus trapping: create a `panelRef = useRef<HTMLDivElement>(null)`, ca
### 2026-03-06 | Architektur | Redis Pub/Sub für SSE
**Problem:** SSE Event-Bus war ein In-Memory-Singleton, funktioniert nicht bei mehreren Server-Instanzen.
**Lösung:** `ioredis` in `@planarchy/api` hinzugefügt. Publisher schreibt Events in Redis-Channel `planarchy:sse`, Subscriber auf jeder Instanz empfängt und liefert lokal aus. Graceful Degradation: bei Redis-Ausfall weiterhin lokale Delivery.
**Lösung:** `ioredis` in `@capakraken/api` hinzugefügt. Publisher schreibt Events in Redis-Channel `planarchy:sse`, Subscriber auf jeder Instanz empfängt und liefert lokal aus. Graceful Degradation: bei Redis-Ausfall weiterhin lokale Delivery.
**Import-Pattern:** `import { Redis } from "ioredis"` (named export, nicht default) notwendig mit `moduleResolution: NodeNext` + ioredis v5.
**Offene Frage:** In Dev-Umgebung reicht lokale Delivery; Redis läuft auf Port 6380 via Docker Compose.
+2 -2
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Admin Pages", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
@@ -21,7 +21,7 @@ test.describe("Admin Pages", () => {
await expect(page.locator("h1", { hasText: /User Management/i })).toBeVisible({ timeout: 10000 });
// Should show a table with at least the admin user
await expect(page.locator("table")).toBeVisible({ timeout: 10000 });
await expect(page.locator("text=admin@planarchy.dev")).toBeVisible({ timeout: 10000 });
await expect(page.locator("text=admin@capakraken.dev")).toBeVisible({ timeout: 10000 });
});
test("roles page loads", async ({ page }) => {
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Allocations", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+1 -1
View File
@@ -8,7 +8,7 @@ test.describe("Authentication", () => {
test("admin can sign in", async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Dashboard", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Estimates", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Navigation", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Projects", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "manager@planarchy.dev");
await page.fill('input[type="email"]', "manager@capakraken.dev");
await page.fill('input[type="password"]', "manager123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/resources/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Resources", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "manager@planarchy.dev");
await page.fill('input[type="email"]', "manager@capakraken.dev");
await page.fill('input[type="password"]', "manager123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/resources/);
+1 -1
View File
@@ -3,7 +3,7 @@ import { expect, test } from "@playwright/test";
test.describe("Staffing", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+2 -2
View File
@@ -5,10 +5,10 @@ test.describe("Timeline", () => {
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
localStorage.setItem("planarchy_theme", JSON.stringify({ mode: "dark" }));
localStorage.setItem("capakraken_theme", JSON.stringify({ mode: "dark" }));
});
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+2 -2
View File
@@ -4,7 +4,7 @@ test.describe("Vacations", () => {
test.describe("My Vacations (self-service)", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
@@ -38,7 +38,7 @@ test.describe("Vacations", () => {
test.describe("Vacation Management", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/auth/signin");
await page.fill('input[type="email"]', "admin@planarchy.dev");
await page.fill('input[type="email"]', "admin@capakraken.dev");
await page.fill('input[type="password"]', "admin123");
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/\/(dashboard|resources)/);
+6 -6
View File
@@ -8,12 +8,12 @@ const nextConfig: NextConfig = {
optimizePackageImports: ["recharts", "date-fns"],
},
transpilePackages: [
"@planarchy/api",
"@planarchy/db",
"@planarchy/engine",
"@planarchy/shared",
"@planarchy/staffing",
"@planarchy/ui",
"@capakraken/api",
"@capakraken/db",
"@capakraken/engine",
"@capakraken/shared",
"@capakraken/staffing",
"@capakraken/ui",
],
typedRoutes: true,
async headers() {
+8 -8
View File
@@ -1,5 +1,5 @@
{
"name": "@planarchy/web",
"name": "@capakraken/web",
"version": "0.1.0",
"private": true,
"scripts": {
@@ -15,12 +15,12 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@node-rs/argon2": "^2.0.2",
"@planarchy/api": "workspace:*",
"@planarchy/application": "workspace:*",
"@planarchy/db": "workspace:*",
"@planarchy/engine": "workspace:*",
"@planarchy/shared": "workspace:*",
"@planarchy/ui": "workspace:*",
"@capakraken/api": "workspace:*",
"@capakraken/application": "workspace:*",
"@capakraken/db": "workspace:*",
"@capakraken/engine": "workspace:*",
"@capakraken/shared": "workspace:*",
"@capakraken/ui": "workspace:*",
"@react-pdf/renderer": "^4.3.2",
"@sentry/nextjs": "^10.45.0",
"@tanstack/react-query": "^5.62.16",
@@ -44,7 +44,7 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@planarchy/tsconfig": "workspace:*",
"@capakraken/tsconfig": "workspace:*",
"@playwright/test": "^1.49.1",
"@types/node": "^22.10.2",
"@types/react": "^19.0.6",
@@ -2,7 +2,7 @@
import { useMemo, useState } from "react";
import Link from "next/link";
import { EstimateStatus, type EstimateVersionStatus } from "@planarchy/shared";
import { EstimateStatus, type EstimateVersionStatus } from "@capakraken/shared";
import { clsx } from "clsx";
import { EstimateWizard } from "~/components/estimates/EstimateWizard.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -3,8 +3,8 @@
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { createPortal } from "react-dom";
import { formatDate, formatMoney } from "~/lib/format.js";
import type { Project, ColumnDef } from "@planarchy/shared";
import { ProjectStatus, PROJECT_COLUMNS, BlueprintTarget } from "@planarchy/shared";
import type { Project, ColumnDef } from "@capakraken/shared";
import { ProjectStatus, PROJECT_COLUMNS, BlueprintTarget } from "@capakraken/shared";
import Link from "next/link";
import Image from "next/image";
import { clsx } from "clsx";
@@ -3,9 +3,9 @@
import { createPortal } from "react-dom";
import { useState, useEffect, useCallback, useMemo, useRef, type ReactNode } from "react";
import Link from "next/link";
import type { Resource, SkillEntry } from "@planarchy/shared";
import { RESOURCE_COLUMNS } from "@planarchy/shared";
import { BlueprintTarget, ResourceType } from "@planarchy/shared";
import type { Resource, SkillEntry } from "@capakraken/shared";
import { RESOURCE_COLUMNS } from "@capakraken/shared";
import { BlueprintTarget, ResourceType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { formatMoney } from "~/lib/format.js";
import { generateCsv, downloadCsv } from "~/lib/csv-export.js";
@@ -1,6 +1,6 @@
import { NextResponse } from "next/server";
import { prisma } from "@planarchy/db";
import { checkChargeabilityAlerts } from "@planarchy/api";
import { prisma } from "@capakraken/db";
import { checkChargeabilityAlerts } from "@capakraken/api";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
@@ -1,6 +1,6 @@
import { NextResponse } from "next/server";
import { prisma } from "@planarchy/db";
import { checkPendingEstimateReminders } from "@planarchy/api";
import { prisma } from "@capakraken/db";
import { checkPendingEstimateReminders } from "@capakraken/api";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
@@ -1,6 +1,6 @@
import { NextResponse } from "next/server";
import { prisma } from "@planarchy/db";
import { autoImportPublicHolidays } from "@planarchy/api";
import { prisma } from "@capakraken/db";
import { autoImportPublicHolidays } from "@capakraken/api";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
+1 -1
View File
@@ -1,5 +1,5 @@
import { NextResponse } from "next/server";
import { eventBus } from "@planarchy/api/sse";
import { eventBus } from "@capakraken/api/sse";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
+2 -2
View File
@@ -1,5 +1,5 @@
import { NextResponse } from "next/server";
import { prisma } from "@planarchy/db";
import { prisma } from "@capakraken/db";
import { createConnection } from "net";
export const dynamic = "force-dynamic";
@@ -18,7 +18,7 @@ async function checkPostgres(): Promise<"ok" | "error"> {
/**
* Lightweight Redis PING check using a raw TCP socket.
* Avoids importing ioredis (which is only a dependency of @planarchy/api).
* Avoids importing ioredis (which is only a dependency of @capakraken/api).
*/
async function checkRedis(): Promise<"ok" | "error"> {
return new Promise((resolve) => {
@@ -2,10 +2,10 @@ import { renderToBuffer } from "@react-pdf/renderer";
import { createElement } from "react";
import { NextResponse } from "next/server";
import * as XLSX from "xlsx";
import { buildSplitAllocationReadModel } from "@planarchy/application";
import { anonymizeResource, getAnonymizationDirectory } from "@planarchy/api";
import { prisma } from "@planarchy/db";
import type { AllocationLike } from "@planarchy/shared";
import { buildSplitAllocationReadModel } from "@capakraken/application";
import { anonymizeResource, getAnonymizationDirectory } from "@capakraken/api";
import { prisma } from "@capakraken/db";
import type { AllocationLike } from "@capakraken/shared";
import { auth } from "~/server/auth.js";
import { AllocationReport } from "~/components/reports/AllocationReport.js";
+3 -3
View File
@@ -1,6 +1,6 @@
import { eventBus } from "@planarchy/api/sse";
import { startReminderScheduler } from "@planarchy/api/lib/reminder-scheduler";
import { SSE_EVENT_TYPES } from "@planarchy/shared";
import { eventBus } from "@capakraken/api/sse";
import { startReminderScheduler } from "@capakraken/api/lib/reminder-scheduler";
import { SSE_EVENT_TYPES } from "@capakraken/shared";
import { auth } from "~/server/auth.js";
// Start the reminder scheduler (idempotent — only starts once)
+3 -3
View File
@@ -1,6 +1,6 @@
import { createTRPCContext, loadRoleDefaults } from "@planarchy/api";
import { appRouter } from "@planarchy/api/router";
import { prisma } from "@planarchy/db";
import { createTRPCContext, loadRoleDefaults } from "@capakraken/api";
import { appRouter } from "@capakraken/api/router";
import { prisma } from "@capakraken/db";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import type { NextRequest } from "next/server";
import { auth } from "~/server/auth.js";
+2 -2
View File
@@ -18,7 +18,7 @@ const displayFont = Manrope({
});
export const metadata: Metadata = {
metadataBase: new URL("https://planarchy.hartmut-noerenberg.com"),
metadataBase: new URL("https://capakraken.hartmut-noerenberg.com"),
title: "CapaKraken — Resource & Capacity Planning",
description: "Interactive resource planning and project staffing tool",
manifest: "/manifest.json",
@@ -51,7 +51,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<head>
<script dangerouslySetInnerHTML={{__html: `
try {
var p = JSON.parse(localStorage.getItem('planarchy_theme') || '{}');
var p = JSON.parse(localStorage.getItem('capakraken_theme') || '{}');
if (p.mode === 'dark') document.documentElement.classList.add('dark');
if (p.accent) document.documentElement.setAttribute('data-accent', p.accent);
} catch(e) {}
@@ -3,7 +3,7 @@
import { useState, useRef } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { parseSkillMatrixWorkbook, matchRoleName } from "~/lib/skillMatrixParser.js";
import type { SkillEntry } from "@planarchy/shared";
import type { SkillEntry } from "@capakraken/shared";
interface ParsedEntry {
fileName: string;
@@ -3,8 +3,8 @@
import { useState } from "react";
import Link from "next/link";
import { clsx } from "clsx";
import { Button } from "@planarchy/ui";
import { Badge } from "@planarchy/ui";
import { Button } from "@capakraken/ui";
import { Badge } from "@capakraken/ui";
import { trpc } from "~/lib/trpc/client.js";
import { AnimatedModal } from "~/components/ui/AnimatedModal.js";
import { ShimmerSkeleton } from "~/components/ui/ShimmerSkeleton.js";
@@ -3,8 +3,8 @@
import { useState } from "react";
import Link from "next/link";
import { clsx } from "clsx";
import { Button } from "@planarchy/ui";
import { Badge } from "@planarchy/ui";
import { Button } from "@capakraken/ui";
import { Badge } from "@capakraken/ui";
import { trpc } from "~/lib/trpc/client.js";
import { AnimatedModal } from "~/components/ui/AnimatedModal.js";
import { ConfirmDialog } from "~/components/ui/ConfirmDialog.js";
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { PermissionKey } from "@planarchy/shared";
import { PermissionKey } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -1294,13 +1294,13 @@ export function SystemSettingsClient() {
/>
</div>
<div>
<label className={LABEL_CLASS}><span className="flex items-center">From Address <InfoTooltip content="The sender email address shown in notification emails (e.g. noreply@planarchy.app)." /></span></label>
<label className={LABEL_CLASS}><span className="flex items-center">From Address <InfoTooltip content="The sender email address shown in notification emails (e.g. noreply@capakraken.app)." /></span></label>
<input
type="email"
className={INPUT_CLASS}
value={smtpFrom}
onChange={(e) => setSmtpFrom(e.target.value)}
placeholder="noreply@planarchy.app"
placeholder="noreply@capakraken.app"
/>
</div>
<div className={`${CHECKBOX_ROW_CLASS} pt-0 md:mt-[1.65rem]`}>
@@ -1,7 +1,7 @@
"use client";
import { useState, useMemo } from "react";
import { SystemRole, PermissionKey, ROLE_DEFAULT_PERMISSIONS, type PermissionOverrides } from "@planarchy/shared";
import { SystemRole, PermissionKey, ROLE_DEFAULT_PERMISSIONS, type PermissionOverrides } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { AnimatedModal } from "~/components/ui/AnimatedModal.js";
import { SuccessToast } from "~/components/ui/SuccessToast.js";
@@ -3,8 +3,8 @@
import { useState, useEffect, useRef, useMemo } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { useInvalidatePlanningViews } from "~/hooks/useInvalidatePlanningViews.js";
import { AllocationStatus } from "@planarchy/shared";
import type { AllocationWithDetails, RecurrencePattern } from "@planarchy/shared";
import { AllocationStatus } from "@capakraken/shared";
import type { AllocationWithDetails, RecurrencePattern } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
import { DateInput } from "~/components/ui/DateInput.js";
@@ -4,8 +4,8 @@ import { useState, useEffect, useMemo, useCallback } from "react";
import { formatDate } from "~/lib/format.js";
import { trpc } from "~/lib/trpc/client.js";
import { AllocationModal } from "./AllocationModal.js";
import type { AllocationLike, AllocationReadModel, AllocationWithDetails, ColumnDef } from "@planarchy/shared";
import { AllocationStatus, ALLOCATION_COLUMNS } from "@planarchy/shared";
import type { AllocationLike, AllocationReadModel, AllocationWithDetails, ColumnDef } from "@capakraken/shared";
import { AllocationStatus, ALLOCATION_COLUMNS } from "@capakraken/shared";
import { useSelection } from "~/hooks/useSelection.js";
import { BatchActionBar } from "~/components/ui/BatchActionBar.js";
import { ConfirmDialog } from "~/components/ui/ConfirmDialog.js";
@@ -188,7 +188,7 @@ export function AllocationsClient() {
// ─── View mode: grouped (default) vs flat ──────────────────────────────────
const [viewMode, setViewMode] = useState<"grouped" | "flat">(() => {
if (typeof window === "undefined") return "grouped";
return (localStorage.getItem("planarchy:allocations:viewMode") as "grouped" | "flat") ?? "grouped";
return (localStorage.getItem("capakraken:allocations:viewMode") as "grouped" | "flat") ?? "grouped";
});
const [collapsedGroups, setCollapsedGroups] = useState<Set<string> | "all">("all");
// Track expanded project sub-groups: key = "resourceId::projectId"
@@ -197,7 +197,7 @@ export function AllocationsClient() {
const toggleViewMode = useCallback(() => {
setViewMode((prev) => {
const next = prev === "grouped" ? "flat" : "grouped";
localStorage.setItem("planarchy:allocations:viewMode", next);
localStorage.setItem("capakraken:allocations:viewMode", next);
return next;
});
}, []);
@@ -1,7 +1,7 @@
"use client";
import { useRef, useState, useMemo } from "react";
import { AllocationStatus } from "@planarchy/shared";
import { AllocationStatus } from "@capakraken/shared";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { formatCents, formatDateMedium } from "~/lib/format.js";
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
@@ -1,7 +1,7 @@
"use client";
import { RecurrenceFrequency } from "@planarchy/shared";
import type { RecurrencePattern } from "@planarchy/shared";
import { RecurrenceFrequency } from "@capakraken/shared";
import type { RecurrencePattern } from "@capakraken/shared";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
const WEEKDAY_LABELS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
@@ -40,7 +40,7 @@ interface Message {
content: string;
}
const STORAGE_KEY = "planarchy-chat-messages";
const STORAGE_KEY = "capakraken-chat-messages";
/** Load messages from sessionStorage (survives page reloads, clears on tab close). */
function loadPersistedMessages(): Message[] {
@@ -1,8 +1,8 @@
"use client";
import { useState, useMemo, useCallback } from "react";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition, FieldOption, StaffingRequirement } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition, FieldOption, StaffingRequirement } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { RolePresetsEditor } from "./RolePresetsEditor.js";
import { FieldCard } from "./FieldCard.js";
@@ -1,8 +1,8 @@
"use client";
import { useState } from "react";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition, FieldOption, StaffingRequirement } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition, FieldOption, StaffingRequirement } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { RolePresetsEditor } from "./RolePresetsEditor.js";
@@ -2,8 +2,8 @@
import { useState, useEffect } from "react";
import type { FormEvent, MouseEvent } from "react";
import { BlueprintTarget } from "@planarchy/shared";
import type { BlueprintFieldDefinition } from "@planarchy/shared";
import { BlueprintTarget } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { BlueprintFieldCatalog } from "./BlueprintFieldCatalog.js";
import { useSelection } from "~/hooks/useSelection.js";
@@ -501,7 +501,7 @@ export function BlueprintsClient() {
blueprintName={editingBlueprint.name}
blueprintTarget={editingBlueprint.target}
initialFieldDefs={Array.isArray(editingBlueprint.fieldDefs) ? (editingBlueprint.fieldDefs as BlueprintFieldDefinition[]) : []}
initialRolePresets={Array.isArray(editingBlueprint.rolePresets) ? (editingBlueprint.rolePresets as import("@planarchy/shared").StaffingRequirement[]) : []}
initialRolePresets={Array.isArray(editingBlueprint.rolePresets) ? (editingBlueprint.rolePresets as import("@capakraken/shared").StaffingRequirement[]) : []}
initialTab={editingTab}
onClose={() => setEditingBlueprint(null)}
/>
@@ -1,8 +1,8 @@
"use client";
import { useState } from "react";
import { FieldType } from "@planarchy/shared";
import type { FieldOption } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { FieldOption } from "@capakraken/shared";
import type { CatalogField } from "~/lib/blueprint-field-catalog.js";
// ---------------------------------------------------------------------------
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import type { StaffingRequirement } from "@planarchy/shared";
import type { StaffingRequirement } from "@capakraken/shared";
import { uuid } from "~/lib/uuid.js";
const INPUT_CLS =
@@ -1,6 +1,6 @@
"use client";
import type { DashboardWidgetType } from "@planarchy/shared/types";
import type { DashboardWidgetType } from "@capakraken/shared/types";
import { WIDGET_CATALOG } from "./widget-registry.js";
interface AddWidgetModalProps {
@@ -1,6 +1,6 @@
"use client";
import type { DashboardWidgetConfig, DashboardWidgetType } from "@planarchy/shared/types";
import type { DashboardWidgetConfig, DashboardWidgetType } from "@capakraken/shared/types";
import dynamic from "next/dynamic";
import { Suspense, useState, useRef, useEffect } from "react";
import { useDashboardLayout } from "~/hooks/useDashboardLayout.js";
@@ -2,7 +2,7 @@ import {
DASHBOARD_WIDGET_CATALOG,
type DashboardWidgetCatalogEntry,
type DashboardWidgetType,
} from "@planarchy/shared/types";
} from "@capakraken/shared/types";
import { lazy, type ComponentType, type LazyExoticComponent } from "react";
type WidgetUpdate = Record<string, unknown>;
@@ -5,7 +5,7 @@ import Link from "next/link";
import { trpc } from "~/lib/trpc/client.js";
import type { WidgetProps } from "~/components/dashboard/widget-registry.js";
import { formatCents, formatMoney } from "~/lib/format.js";
import { ProjectStatus } from "@planarchy/shared/types";
import { ProjectStatus } from "@capakraken/shared/types";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { PROJECT_STATUS_BADGE as STATUS_COLORS } from "~/lib/status-styles.js";
import { AnimatedNumber } from "~/components/ui/AnimatedNumber.js";
@@ -2,8 +2,8 @@
import { clsx } from "clsx";
import { DateInput } from "~/components/ui/DateInput.js";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";
interface Props {
fieldDefs: BlueprintFieldDefinition[];
@@ -2,8 +2,8 @@
import { clsx } from "clsx";
import { formatDateLong } from "~/lib/format.js";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";
interface Props {
fieldDefs: BlueprintFieldDefinition[];
@@ -1,12 +1,12 @@
"use client";
import { useEffect, useState } from "react";
import type { CommercialTerms, PaymentMilestone, PricingModel } from "@planarchy/shared";
import type { CommercialTerms, PaymentMilestone, PricingModel } from "@capakraken/shared";
import {
computeCommercialTermsSummary,
computeMilestoneAmounts,
validatePaymentMilestones,
} from "@planarchy/engine";
} from "@capakraken/engine";
import { clsx } from "clsx";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { formatMoney } from "~/lib/format.js";
@@ -1,8 +1,8 @@
"use client";
import { useEffect, useMemo, useRef, useState } from "react";
import { EstimateStatus } from "@planarchy/shared";
import { computeEvenSpread } from "@planarchy/engine";
import { EstimateStatus } from "@capakraken/shared";
import { computeEvenSpread } from "@capakraken/engine";
import { isSpreadsheetFile } from "~/lib/excel.js";
import { parseScopeImport } from "~/lib/scopeImportParser.js";
import { clsx } from "clsx";
@@ -2,7 +2,7 @@ import type {
EstimateDemandLineCalculationMetadata,
EstimateDemandLineMetadata,
EstimateDemandLineRateMode,
} from "@planarchy/shared";
} from "@capakraken/shared";
interface ResourceRateSnapshotLike {
lcrCents: number;
@@ -7,7 +7,7 @@ import type {
EstimateExportFormat,
EstimateStatus,
EstimateVersionStatus,
} from "@planarchy/shared";
} from "@capakraken/shared";
export interface EstimateMetricView {
id: string;
@@ -3,7 +3,7 @@
import { useEffect, useState } from "react";
import Link from "next/link";
import dynamic from "next/dynamic";
import { EstimateExportFormat } from "@planarchy/shared";
import { EstimateExportFormat } from "@capakraken/shared";
import { clsx } from "clsx";
import type {
EstimateWorkspaceView,
@@ -1,13 +1,13 @@
"use client";
import { useEffect, useMemo, useState } from "react";
import type { EstimateDemandLineRateMode } from "@planarchy/shared";
import type { EstimateDemandLineRateMode } from "@capakraken/shared";
import {
computeEvenSpread,
getEstimateMonthRange,
rebalanceSpread,
summarizeMonthlySpread,
} from "@planarchy/engine";
} from "@capakraken/engine";
import {
buildDemandLineMetadata,
getEffectiveDemandLineValues,
@@ -8,7 +8,7 @@ import {
type ChapterSubtotal,
type ResourceSnapshotDiff,
type ScopeItemDiff,
} from "@planarchy/engine";
} from "@capakraken/engine";
import type { EstimateVersionView } from "~/components/estimates/EstimateWorkspace.types.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { formatMoney } from "~/lib/format.js";
@@ -1,11 +1,11 @@
"use client";
import { useMemo } from "react";
import type { EstimateDemandLineRateMode } from "@planarchy/shared";
import type { EstimateDemandLineRateMode } from "@capakraken/shared";
import {
computeEvenSpread,
rebalanceSpread,
} from "@planarchy/engine";
} from "@capakraken/engine";
import {
getEffectiveDemandLineValues,
} from "~/components/estimates/EstimateWorkspace.calculations.js";
@@ -3,7 +3,7 @@
import {
type EstimateExportArtifactPayload,
EstimateExportFormat,
} from "@planarchy/shared";
} from "@capakraken/shared";
import type {
EstimateExportView,
EstimateVersionView,
@@ -1,7 +1,7 @@
"use client";
import { clsx } from "clsx";
import { EstimateStatus, EstimateVersionStatus } from "@planarchy/shared";
import { EstimateStatus, EstimateVersionStatus } from "@capakraken/shared";
import type {
EstimateMetricView,
EstimateVersionView,
@@ -1,7 +1,7 @@
"use client";
import { EstimateVersionStatus } from "@planarchy/shared";
import { summarizeMonthlySpread } from "@planarchy/engine";
import { EstimateVersionStatus } from "@capakraken/shared";
import { summarizeMonthlySpread } from "@capakraken/engine";
import { clsx } from "clsx";
import {
getEffectiveDemandLineValues,
@@ -1,6 +1,6 @@
"use client";
import { EstimateVersionStatus } from "@planarchy/shared";
import { EstimateVersionStatus } from "@capakraken/shared";
import { clsx } from "clsx";
import { VersionCompare } from "~/components/estimates/VersionCompare.js";
import type {
+1 -1
View File
@@ -15,7 +15,7 @@ import { NotificationBell } from "../notifications/NotificationBell.js";
import { ChatPanel } from "../assistant/ChatPanel.js";
import { NavProgressBar } from "~/components/ui/NavProgressBar.js";
const SIDEBAR_COLLAPSED_KEY = "planarchy_sidebar_collapsed";
const SIDEBAR_COLLAPSED_KEY = "capakraken_sidebar_collapsed";
function IconFrame({ children }: { children: ReactNode }) {
return (
@@ -2,7 +2,7 @@
import { useCallback, useEffect, useRef, useState } from "react";
const DISMISS_KEY = "planarchy_pwa_dismiss";
const DISMISS_KEY = "capakraken_pwa_dismiss";
const DISMISS_DURATION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
interface BeforeInstallPromptEvent extends Event {
@@ -9,7 +9,7 @@ import { useEffect } from "react";
export function ThemeProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
try {
const raw = localStorage.getItem("planarchy_theme");
const raw = localStorage.getItem("capakraken_theme");
if (!raw) return;
const prefs = JSON.parse(raw) as { mode?: string; accent?: string };
const html = document.documentElement;
@@ -6,7 +6,7 @@ import { formatCents, formatDate } from "~/lib/format.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { FillOpenDemandModal } from "~/components/allocations/FillOpenDemandModal.js";
import { AllocationModal } from "~/components/allocations/AllocationModal.js";
import type { AllocationWithDetails } from "@planarchy/shared";
import type { AllocationWithDetails } from "@capakraken/shared";
import type { OpenDemandAssignment } from "~/components/timeline/TimelineProjectPanel.js";
import { usePermissions } from "~/hooks/usePermissions.js";
import { trpc } from "~/lib/trpc/client.js";
@@ -2,7 +2,7 @@
import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import type { Project } from "@planarchy/shared";
import type { Project } from "@capakraken/shared";
import { ProjectModal } from "./ProjectModal.js";
import { ConfirmDialog } from "~/components/ui/ConfirmDialog.js";
import { usePermissions } from "~/hooks/usePermissions.js";
@@ -2,8 +2,8 @@
import { useState, useEffect, useRef } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { OrderType, AllocationType, ProjectStatus } from "@planarchy/shared";
import type { Project } from "@planarchy/shared";
import { OrderType, AllocationType, ProjectStatus } from "@capakraken/shared";
import type { Project } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { DateInput } from "~/components/ui/DateInput.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -2,8 +2,8 @@
import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { clsx } from "clsx";
import type { StaffingRequirement } from "@planarchy/shared";
import { BlueprintTarget, OrderType, AllocationType, ProjectStatus, AllocationStatus } from "@planarchy/shared";
import type { StaffingRequirement } from "@capakraken/shared";
import { BlueprintTarget, OrderType, AllocationType, ProjectStatus, AllocationStatus } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { uuid } from "~/lib/uuid.js";
import { DateInput } from "~/components/ui/DateInput.js";
@@ -656,7 +656,7 @@ function Step3({ state, onChange }: Step3Props) {
// ─── Step 4: Suggestions ─────────────────────────────────────────────────────
// Matches StaffingSuggestion from @planarchy/shared (returned by staffing.getSuggestions)
// Matches StaffingSuggestion from @capakraken/shared (returned by staffing.getSuggestions)
type SuggestionItem = {
resourceId: string;
resourceName: string;
@@ -1,8 +1,8 @@
"use client";
import { useState } from "react";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
const INPUT_CLS =
@@ -3,7 +3,7 @@
import { useState } from "react";
import Link from "next/link";
import dynamic from "next/dynamic";
import type { AllocationLike, AllocationReadModel, AllocationWithDetails, Resource, SkillEntry } from "@planarchy/shared";
import type { AllocationLike, AllocationReadModel, AllocationWithDetails, Resource, SkillEntry } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { formatDate, formatMoney } from "~/lib/format.js";
import { ResourceModal } from "./ResourceModal.js";
@@ -2,8 +2,8 @@
import { useRef, useState } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import type { Resource, SkillEntry } from "@planarchy/shared";
import { GERMAN_FEDERAL_STATES, inferStateFromPostalCode, ResourceType } from "@planarchy/shared";
import type { Resource, SkillEntry } from "@capakraken/shared";
import { GERMAN_FEDERAL_STATES, inferStateFromPostalCode, ResourceType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -3,7 +3,7 @@
import { useState, useRef } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { parseSkillMatrixWorkbook, matchRoleName } from "~/lib/skillMatrixParser.js";
import type { SkillEntry } from "@planarchy/shared";
import type { SkillEntry } from "@capakraken/shared";
interface Props {
resourceId: string;
@@ -8,7 +8,7 @@ import {
Radar,
Tooltip,
} from "recharts";
import type { SkillEntry } from "@planarchy/shared";
import type { SkillEntry } from "@capakraken/shared";
interface Props {
skills: SkillEntry[];
+1 -1
View File
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import type { RoleWithResourceCount } from "@planarchy/shared";
import type { RoleWithResourceCount } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { AnimatedModal } from "~/components/ui/AnimatedModal.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import type { RoleWithResourceCount } from "@planarchy/shared";
import type { RoleWithResourceCount } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { RoleModal } from "./RoleModal.js";
import { FilterChips } from "~/components/ui/FilterChips.js";
@@ -3,12 +3,12 @@
import { useState, useCallback } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidatePlanningViews } from "~/hooks/useInvalidatePlanningViews.js";
import { AllocationStatus } from "@planarchy/shared";
import { AllocationStatus } from "@capakraken/shared";
import { DateInput } from "~/components/ui/DateInput.js";
import { SkillTagInput } from "~/components/ui/SkillTagInput.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { SuccessToast } from "~/components/ui/SuccessToast.js";
import { Button } from "@planarchy/ui";
import { Button } from "@capakraken/ui";
interface SearchCriteria {
startDate: string;
@@ -2,7 +2,7 @@
import { clsx } from "clsx";
import { useEffect, useRef, useState } from "react";
import type { AllocationLike, AllocationReadModel, Assignment } from "@planarchy/shared";
import type { AllocationLike, AllocationReadModel, Assignment } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidateTimeline } from "~/hooks/useInvalidatePlanningViews.js";
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
@@ -2,7 +2,7 @@
import { clsx } from "clsx";
import { useEffect, useRef, useState } from "react";
import { AllocationStatus } from "@planarchy/shared";
import { AllocationStatus } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidateTimeline } from "~/hooks/useInvalidatePlanningViews.js";
@@ -2,7 +2,7 @@
import { clsx } from "clsx";
import { useEffect, useRef, useState } from "react";
import { AllocationStatus } from "@planarchy/shared";
import { AllocationStatus } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidateTimeline } from "~/hooks/useInvalidatePlanningViews.js";
import { DateInput } from "~/components/ui/DateInput.js";
@@ -2,7 +2,7 @@
import { clsx } from "clsx";
import { useEffect, useState } from "react";
import { AllocationStatus, type StaffingRequirement } from "@planarchy/shared";
import { AllocationStatus, type StaffingRequirement } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidateTimeline } from "~/hooks/useInvalidatePlanningViews.js";
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
@@ -3,7 +3,7 @@
import { useEffect, useRef, useState } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { formatCents } from "~/lib/format.js";
import type { SkillEntry } from "@planarchy/shared";
import type { SkillEntry } from "@capakraken/shared";
interface ResourceHoverCardProps {
resourceId: string;
@@ -6,7 +6,7 @@ import {
type AllocationReadModel,
type Assignment,
type DemandRequirement,
} from "@planarchy/shared";
} from "@capakraken/shared";
import { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { useSearchParams } from "next/navigation";
import { useTimelineSSE } from "~/hooks/useTimelineSSE.js";
@@ -1,7 +1,7 @@
"use client";
import { useState, useRef, useEffect, useCallback } from "react";
import type { ColumnDef } from "@planarchy/shared";
import type { ColumnDef } from "@capakraken/shared";
interface ColumnTogglePanelProps {
allColumns: ColumnDef[];
@@ -1,7 +1,7 @@
"use client";
import { FieldType } from "@planarchy/shared";
import type { BlueprintFieldDefinition } from "@planarchy/shared";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition } from "@capakraken/shared";
import type { CustomFieldFilter } from "~/hooks/useFilters.js";
interface Props {
@@ -2,7 +2,7 @@
import { useCallback } from "react";
import { trpc } from "~/lib/trpc/client.js";
import type { ProjectStatus } from "@planarchy/shared";
import type { ProjectStatus } from "@capakraken/shared";
import { EntityCombobox } from "./EntityCombobox.js";
type ProjectItem = { id: string; shortCode: string; name: string };
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { VacationStatus, VacationType } from "@planarchy/shared";
import { VacationStatus, VacationType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { VacationModal } from "./VacationModal.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { GERMAN_FEDERAL_STATES } from "@planarchy/shared";
import { GERMAN_FEDERAL_STATES } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
export function PublicHolidayBatch() {
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { VacationStatus } from "@planarchy/shared";
import { VacationStatus } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { VACATION_CALENDAR_COLORS } from "~/lib/status-styles.js";
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { VacationStatus, VacationType } from "@planarchy/shared";
import { VacationStatus, VacationType } from "@capakraken/shared";
import { VACATION_CALENDAR_COLORS } from "~/lib/status-styles.js";
interface VacationEntry {
@@ -1,7 +1,7 @@
"use client";
import { useState, useCallback } from "react";
import { VacationStatus, VacationType } from "@planarchy/shared";
import { VacationStatus, VacationType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { VacationModal } from "./VacationModal.js";
import { TeamCalendar } from "./TeamCalendar.js";
@@ -2,7 +2,7 @@
import { useRef, useState } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { VacationType } from "@planarchy/shared";
import { VacationType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { DateInput } from "~/components/ui/DateInput.js";
import { useDebounce } from "~/hooks/useDebounce.js";
+2 -2
View File
@@ -22,8 +22,8 @@ export interface AppPreferences {
blinkOverbookedDays: boolean;
}
const STORAGE_KEY = "planarchy_prefs";
const CHANGE_EVENT = "planarchy-prefs-changed";
const STORAGE_KEY = "capakraken_prefs";
const CHANGE_EVENT = "capakraken-prefs-changed";
const DEFAULT: AppPreferences = {
hideCompletedProjects: true,
+1 -1
View File
@@ -1,7 +1,7 @@
"use client";
import { useMemo, useCallback, useState } from "react";
import type { ColumnDef, ColumnPreferences, ViewKey } from "@planarchy/shared";
import type { ColumnDef, ColumnPreferences, ViewKey } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
// Simple localStorage helper (no external lib needed)
+3 -3
View File
@@ -4,16 +4,16 @@ import { useState, useCallback, useEffect, useRef } from "react";
import {
type DashboardLayoutConfig,
type DashboardWidgetType,
} from "@planarchy/shared/types";
} from "@capakraken/shared/types";
import {
createDashboardWidget,
createDefaultDashboardLayout,
getNextDashboardWidgetY,
normalizeDashboardLayout,
} from "@planarchy/shared/schemas";
} from "@capakraken/shared/schemas";
import { trpc } from "~/lib/trpc/client.js";
const STORAGE_KEY = "planarchy_dashboard_v1";
const STORAGE_KEY = "capakraken_dashboard_v1";
function generateWidgetId() {
return `widget-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;

Some files were not shown because too many files have changed in this diff Show More