feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit f935754df4
120 changed files with 21772 additions and 90 deletions

View File

@@ -0,0 +1,24 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call([
RoleSeeder::class,
ProjectStatusSeeder::class,
ProjectTypeSeeder::class,
UserSeeder::class,
]);
}
}

View File

@@ -0,0 +1,103 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ProjectStatusSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$statuses = [
[
'name' => 'Pre-sales',
'order' => 1,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'SOW Approval',
'order' => 2,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Estimation',
'order' => 3,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Estimate Approved',
'order' => 4,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Resource Allocation',
'order' => 5,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Sprint 0',
'order' => 6,
'is_active' => true,
'is_billable' => false,
],
[
'name' => 'In Progress',
'order' => 7,
'is_active' => true,
'is_billable' => true,
],
[
'name' => 'UAT',
'order' => 8,
'is_active' => true,
'is_billable' => true,
],
[
'name' => 'Handover / Sign-off',
'order' => 9,
'is_active' => true,
'is_billable' => true,
],
[
'name' => 'Estimate Rework',
'order' => 10,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'On Hold',
'order' => 11,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Cancelled',
'order' => 12,
'is_active' => false,
'is_billable' => false,
],
[
'name' => 'Closed',
'order' => 13,
'is_active' => false,
'is_billable' => false,
],
];
foreach ($statuses as $status) {
DB::table('project_statuses')->updateOrInsert(
['name' => $status['name']],
$status
);
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ProjectTypeSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$types = [
[
'name' => 'Project',
'description' => 'Full software development project with defined scope, timeline, and deliverables',
],
[
'name' => 'Support',
'description' => 'Ongoing support and maintenance with SLA requirements',
],
];
foreach ($types as $type) {
DB::table('project_types')->updateOrInsert(
['name' => $type['name']],
$type
);
}
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$roles = [
[
'name' => 'Frontend Dev',
'description' => 'Frontend Developer - specializes in UI/UX and client-side development',
],
[
'name' => 'Backend Dev',
'description' => 'Backend Developer - specializes in server-side logic and APIs',
],
[
'name' => 'QA',
'description' => 'Quality Assurance - tests software and ensures quality standards',
],
[
'name' => 'DevOps',
'description' => 'DevOps Engineer - manages infrastructure, CI/CD, and deployments',
],
[
'name' => 'UX',
'description' => 'UX Designer - designs user experiences and interfaces',
],
[
'name' => 'PM',
'description' => 'Project Manager - manages projects, timelines, and client communication',
],
[
'name' => 'Architect',
'description' => 'Solution Architect - designs system architecture and technical solutions',
],
];
foreach ($roles as $role) {
DB::table('roles')->updateOrInsert(
['name' => $role['name']],
$role
);
}
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class UserSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Create superuser for testing
DB::table('users')->updateOrInsert(
['email' => 'superuser@headroom.test'],
[
'id' => (string) Str::uuid(),
'name' => 'Super User',
'email' => 'superuser@headroom.test',
'password' => Hash::make('password'),
'role' => 'superuser',
'created_at' => now(),
'updated_at' => now(),
]
);
// Create test users for each role
$testUsers = [
[
'name' => 'Manager User',
'email' => 'manager@headroom.test',
'role' => 'manager',
],
[
'name' => 'Developer User',
'email' => 'developer@headroom.test',
'role' => 'developer',
],
[
'name' => 'Top Brass User',
'email' => 'topbrass@headroom.test',
'role' => 'top_brass',
],
];
foreach ($testUsers as $user) {
DB::table('users')->updateOrInsert(
['email' => $user['email']],
[
'id' => (string) Str::uuid(),
'name' => $user['name'],
'email' => $user['email'],
'password' => Hash::make('password'),
'role' => $user['role'],
'created_at' => now(),
'updated_at' => now(),
]
);
}
}
}