Full enterprise web operating system including: - Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui - NestJS 10 backend with Prisma, JWT auth, Swagger docs - Keycloak 24 SSO with role-based access control - HR module (employees, time tracking, absences, org chart) - LEAN module (3S planning, morning meeting SQCDM, skill matrix) - Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs) - Dashboard with customizable drag & drop widget grid - Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
3.2 KiB
Markdown
70 lines
3.2 KiB
Markdown
# @tos/shared Package Integration
|
|
|
|
## Package Location
|
|
`packages/shared/` - Built with tsup, outputs CJS + ESM + types to `dist/`
|
|
|
|
## Available Exports
|
|
|
|
### Utils (`@tos/shared` or `@tos/shared/utils`)
|
|
- `formatDate(date, options?)` - German locale, 2-digit format (dd.MM.yyyy)
|
|
- `formatTime(date, options?)` - German locale, HH:mm
|
|
- `formatDateTime(date)` - Combined date + time
|
|
- `calculateWorkingDays(start, end)` - Excludes weekends
|
|
- `minutesToHoursAndMinutes(mins)` - Returns { hours, minutes }
|
|
- `formatMinutesToTime(mins)` - Returns "HH:MM" string
|
|
- `getInitials(firstName, lastName)` - Two-arg version, returns "FL"
|
|
- `getFullName(firstName, lastName)` - Returns "First Last"
|
|
- `slugify(str)` - URL-safe slug
|
|
- `isDefined<T>(value)` - Type guard for non-null/undefined
|
|
- `sleep(ms)` - Promise-based delay
|
|
|
|
### Constants (`@tos/shared`)
|
|
- `DEFAULT_VACATION_DAYS`, `MIN_VACATION_DAYS`
|
|
- `STANDARD_WORKING_HOURS_PER_WEEK/DAY`, `MAX_WORKING_HOURS_PER_DAY`
|
|
- `DEFAULT_BREAK_MINUTES`, `REQUIRED_BREAK_MINUTES`, `EXTENDED_BREAK_MINUTES`
|
|
- `SKILL_LEVELS`, `S3_CATEGORIES`, `SQCDM_CATEGORIES`
|
|
- `HTTP_STATUS`, `DATE_FORMATS`
|
|
- `API_VERSION`, `API_PREFIX`, `DEFAULT_PAGE_SIZE`, `MAX_PAGE_SIZE`
|
|
- `PERMISSIONS`, `ROLE_PERMISSIONS`
|
|
|
|
### Types (`@tos/shared` or `@tos/shared/types`)
|
|
- `User`, `UserRole`, `UserPreferences`, `DashboardWidgetConfig`, `NotificationPreferences`
|
|
- `CreateUserDto`, `UpdateUserDto`
|
|
- `Department`, `DepartmentCode`, `DepartmentWithStats`, `CreateDepartmentDto`, `UpdateDepartmentDto`
|
|
- `Employee`, `ContractType`, `TimeEntry`, `TimeEntryType`, `Absence`, `AbsenceType`, `ApprovalStatus`
|
|
- `AuthUser`, `TokenPayload`, `LoginRequest`, `AuthResponse`, `Permission`
|
|
- Skill Matrix: `Skill`, `SkillMatrixEntry`, `SkillMatrix`, `SkillGapAnalysis`, etc.
|
|
|
|
## Integration Patterns
|
|
|
|
### Web App (apps/web)
|
|
- `transpilePackages: ['@tos/shared']` in next.config.mjs (transpiles source directly)
|
|
- `"@tos/shared": "workspace:*"` in package.json
|
|
- Import directly: `import { getInitials } from '@tos/shared'`
|
|
|
|
### API App (apps/api)
|
|
- `"@tos/shared": "workspace:*"` in package.json
|
|
- Uses built dist (CJS) - requires `pnpm --filter @tos/shared build` first
|
|
- Import: `import { calculateWorkingDays, DEFAULT_VACATION_DAYS } from '@tos/shared'`
|
|
|
|
## Key Differences: Local vs Shared
|
|
|
|
### getInitials
|
|
- **Shared**: `getInitials(firstName: string, lastName: string)` - two args
|
|
- **Web local** (`@/lib/utils`): `getInitials(name: string)` - single full name string, splits on space
|
|
- Both coexist; use shared in components with firstName/lastName, local in header with full name
|
|
|
|
### Date Formatting
|
|
- **Shared**: `formatDate()` uses `{ day: '2-digit', month: '2-digit', year: 'numeric' }`, hardcoded `de-DE`
|
|
- **Web local**: `formatDate()` uses `{ year: 'numeric', month: 'long', day: 'numeric' }`, accepts locale param
|
|
- **Web local**: `formatDateShort()` is equivalent to shared `formatDate()` but accepts locale param
|
|
- NOT interchangeable - different output format
|
|
|
|
### sleep
|
|
- Identical in both - web local now re-exports from `@tos/shared`
|
|
|
|
### ApprovalStatus / ContractType
|
|
- **Shared**: UPPERCASE (`'PENDING'`, `'FULL_TIME'`)
|
|
- **Web types**: lowercase (`'pending'`, `'full_time'`)
|
|
- NOT interchangeable - different casing convention
|