1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 23:13:42 +01:00

feat(frontend): TypeScript-Monorepo mit Terminal-UI für Effigenix ERP

Monorepo-Setup (pnpm workspaces) mit vier shared Packages und einer TUI-App:

Shared Packages:
- @effigenix/types: TypeScript-DTOs (UserDTO, RoleDTO, AuthDTO, Enums)
- @effigenix/config: API-Konfiguration und Shared Constants
- @effigenix/validation: Zod-Schemas für Username, E-Mail und Passwort
- @effigenix/api-client: axios-Client mit JWT-Handling (proaktiver + reaktiver
  Token-Refresh), AuthInterceptor, ErrorInterceptor, Resources für auth/users/roles

TUI (apps/cli, Ink 5 / React):
- Authentication: Login/Logout, Session-Restore beim Start, JWT-Refresh
- User Management: Liste, Anlage (Zod-Inline-Validation), Detailansicht,
  Passwort ändern, Sperren/Entsperren mit ConfirmDialog
- Role Management: Liste, Detailansicht, Zuweisen/Entfernen per RoleSelectList (↑↓)
- UX: SuccessDisplay (Auto-Dismiss 3 s), ConfirmDialog (J/N),
  FormInput mit Inline-Fehlern, StatusBar mit API-URL
- Layout: Fullscreen-Modus (alternate screen buffer), Header mit eingeloggtem User
- Tests: vitest + ink-testing-library (15 Tests)
This commit is contained in:
Sebastian Frick 2026-02-18 12:23:11 +01:00
parent 87123df2e4
commit bbe9e87c33
65 changed files with 6955 additions and 1 deletions

View file

@ -0,0 +1,14 @@
import { z } from 'zod';
import { usernameSchema } from '../validators.js';
export const loginRequestSchema = z.object({
username: usernameSchema,
password: z.string().min(1, 'Passwort ist erforderlich'),
});
export const refreshTokenRequestSchema = z.object({
refreshToken: z.string().min(1, 'Refresh Token ist erforderlich'),
});
export type LoginRequestInput = z.input<typeof loginRequestSchema>;
export type LoginRequestOutput = z.output<typeof loginRequestSchema>;

View file

@ -0,0 +1,37 @@
import { z } from 'zod';
import { emailSchema, passwordSchema, usernameSchema, uuidSchema } from '../validators.js';
export const createUserRequestSchema = z.object({
username: usernameSchema,
email: emailSchema,
password: passwordSchema,
roleIds: z.array(uuidSchema).min(1, 'Mindestens eine Rolle muss zugewiesen werden'),
branchId: uuidSchema.optional(),
});
export const updateUserRequestSchema = z.object({
email: emailSchema.optional(),
branchId: uuidSchema.optional(),
});
export const changePasswordRequestSchema = z
.object({
currentPassword: z.string().min(1, 'Aktuelles Passwort ist erforderlich'),
newPassword: passwordSchema,
confirmPassword: z.string().min(1, 'Passwortbestätigung ist erforderlich'),
})
.refine((data) => data.newPassword === data.confirmPassword, {
message: 'Passwörter stimmen nicht überein',
path: ['confirmPassword'],
});
export const assignRoleRequestSchema = z.object({
roleId: uuidSchema,
});
export type CreateUserRequestInput = z.input<typeof createUserRequestSchema>;
export type CreateUserRequestOutput = z.output<typeof createUserRequestSchema>;
export type UpdateUserRequestInput = z.input<typeof updateUserRequestSchema>;
export type UpdateUserRequestOutput = z.output<typeof updateUserRequestSchema>;
export type ChangePasswordRequestInput = z.input<typeof changePasswordRequestSchema>;
export type AssignRoleRequestInput = z.input<typeof assignRoleRequestSchema>;