Initial commit: everythingbutwork MVP
Internes Project-Management-Tool für ToolCTRL — ergänzend zu Plane (Tickets) und Outline (Doku). Umfasst Puls-Übersicht, Tagesrhythmus (Lock-in + Reflexion), Bereichs-Detail-Views (Entwicklung/Vertrieb/Marketing), Pflicht-Minimum-Check und Blocker-Lifecycle gemäß Projektmanagement-Leitfaden v3.0. Stack: pnpm-Monorepo · Vite + React 18 + Tailwind · Fastify + tRPC v11 + Drizzle ORM · Postgres 16 · Authentik OIDC (Phase 2, Dev-Auto-Login aktiv). Planungs-Artefakte unter _bmad-output/planning-artifacts/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
4f33509a0f
131 files changed
+34339
No files matched your search
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@cockpit/shared",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./schemas/*": "./src/schemas/*.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build": "tsc",
|
||||
"test": "vitest run --passWithNoTests"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.2",
|
||||
"vitest": "^2.1.8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Konstanten, die zwischen Frontend und Backend identisch genutzt werden.
|
||||
|
||||
export const MAX_TODO_TEXT_LENGTH = 200;
|
||||
export const MAX_REFLECTION_TEXT_LENGTH = 1000;
|
||||
export const WERKTAGE = ['MO', 'DI', 'MI', 'DO', 'FR'] as const;
|
||||
export const JOURFIXE_DAY = 'DI' as const; // Di 11:00 als Default
|
||||
export const JOURFIXE_HOUR = 11;
|
||||
export const REFLEXION_REMINDER_HOUR = 17;
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from './constants.js';
|
||||
export * as DayEntrySchemas from './schemas/day-entry.js';
|
||||
export * as ProjectSchemas from './schemas/project.js';
|
||||
export * as DealSchemas from './schemas/deal.js';
|
||||
export * as CampaignSchemas from './schemas/campaign.js';
|
||||
|
||||
export const SHARED_VERSION = '0.0.2';
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const createCampaignInput = z.object({
|
||||
name: z.string().min(1).max(200),
|
||||
status: z.enum(['active', 'paused', 'done']).default('active'),
|
||||
reach: z.number().int().min(0).default(0),
|
||||
ownerUserId: z.string().uuid().optional(),
|
||||
});
|
||||
export type CreateCampaignInput = z.infer<typeof createCampaignInput>;
|
||||
@@ -0,0 +1,59 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ampelSchema = z.enum(['green', 'amber', 'red']);
|
||||
export const trendSchema = z.enum(['besser', 'gleich', 'schlechter']);
|
||||
export const bezugKindSchema = z.enum(['project', 'deal', 'campaign', 'allgemein']);
|
||||
export const todoStatusSchema = z.enum(['open', 'done', 'dropped']);
|
||||
|
||||
export const todoInputSchema = z.object({
|
||||
title: z.string().min(1).max(200),
|
||||
bezugKind: bezugKindSchema.optional(),
|
||||
bezugId: z.string().uuid().optional(),
|
||||
});
|
||||
export type TodoInput = z.infer<typeof todoInputSchema>;
|
||||
|
||||
export const checkInInput = z.object({
|
||||
todos: z.array(todoInputSchema).min(1),
|
||||
date: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
||||
.optional(), // Default: heute
|
||||
});
|
||||
export type CheckInInput = z.infer<typeof checkInInput>;
|
||||
|
||||
export const submitReflectionInput = z.object({
|
||||
dayEntryId: z.string().uuid(),
|
||||
todos: z
|
||||
.array(
|
||||
z.object({
|
||||
id: z.string().uuid(),
|
||||
status: todoStatusSchema,
|
||||
dropReason: z.string().max(200).optional(),
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
reflectionText: z.string().max(1000).default(''),
|
||||
ampel: ampelSchema,
|
||||
trend: trendSchema.nullable().optional(),
|
||||
blocker: z
|
||||
.object({
|
||||
title: z.string().min(1).max(200),
|
||||
description: z.string().max(1000).optional(),
|
||||
})
|
||||
.optional(),
|
||||
url: z.string().url().optional(),
|
||||
});
|
||||
export type SubmitReflectionInput = z.infer<typeof submitReflectionInput>;
|
||||
|
||||
export const todoMutationInput = z.object({
|
||||
dayEntryId: z.string().uuid(),
|
||||
todos: z.array(todoInputSchema).min(0),
|
||||
});
|
||||
export type TodoMutationInput = z.infer<typeof todoMutationInput>;
|
||||
|
||||
export const markAbsentInput = z.object({
|
||||
from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
||||
to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
||||
reason: z.enum(['urlaub', 'krank', 'sonstiges']),
|
||||
});
|
||||
export type MarkAbsentInput = z.infer<typeof markAbsentInput>;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const dealStageSchema = z.enum(['lead', 'erstgespraech', 'demo', 'angebot', 'abschluss']);
|
||||
export const DEAL_STAGES = dealStageSchema.options;
|
||||
|
||||
export const createDealInput = z.object({
|
||||
name: z.string().min(1).max(200),
|
||||
ownerUserId: z.string().uuid().optional(),
|
||||
valueEur: z.number().int().min(0),
|
||||
probability: z.number().int().min(0).max(100).default(50),
|
||||
stage: dealStageSchema.default('lead'),
|
||||
});
|
||||
export type CreateDealInput = z.infer<typeof createDealInput>;
|
||||
|
||||
export const updateDealStageInput = z.object({
|
||||
dealId: z.string().uuid(),
|
||||
stage: dealStageSchema,
|
||||
});
|
||||
export type UpdateDealStageInput = z.infer<typeof updateDealStageInput>;
|
||||
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const createProjectInput = z.object({
|
||||
areaId: z.string().uuid(),
|
||||
name: z.string().min(1).max(200),
|
||||
kind: z.enum(['kundenprojekt', 'internes_projekt']),
|
||||
verantwortlicheUserId: z.string().uuid().optional(),
|
||||
arbeitsmodus: z.enum(['cycle', 'kanban']).optional(),
|
||||
outlineSteckbriefUrl: z.string().url(),
|
||||
planeProjectUrl: z.string().url(),
|
||||
risikolisteUrl: z.string().url().optional(),
|
||||
dodText: z.string().max(2000).optional(),
|
||||
start: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
||||
.optional(),
|
||||
deadline: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
||||
.optional(),
|
||||
milestones: z
|
||||
.array(
|
||||
z.object({
|
||||
title: z.string().min(1).max(200),
|
||||
due: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
||||
.optional(),
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
});
|
||||
export type CreateProjectInput = z.infer<typeof createProjectInput>;
|
||||
|
||||
export const archiveProjectInput = z.object({
|
||||
projectId: z.string().uuid(),
|
||||
lessonsLearnedUrl: z.string().url(),
|
||||
});
|
||||
export type ArchiveProjectInput = z.infer<typeof archiveProjectInput>;
|
||||
|
||||
export const setMilestoneStatusInput = z.object({
|
||||
milestoneId: z.string().uuid(),
|
||||
status: z.enum(['open', 'done', 'overdue']),
|
||||
});
|
||||
export type SetMilestoneStatusInput = z.infer<typeof setMilestoneStatusInput>;
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Reference in new issue
Block a user