feat(db): add schedule tasks for N-001 and remove demo

Seed N-001-1234-Johnson with 41 construction tasks across
all phases (preconstruction through closeout), 19 FS
dependencies, and 4 milestones. Remove legacy demo project.
Fix project list to order by name for consistent first load.
This commit is contained in:
Nicholai Vogel 2026-01-24 13:36:18 -07:00
parent a09024aff7
commit d980ac6d8f
2 changed files with 110 additions and 46 deletions

View File

@ -1,5 +1,9 @@
-- Seed data for COMPASS
-- Run with: wrangler d1 execute compass-db --local --file=seed.sql
-- Run with: sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/<hash>.sqlite < seed.sql
-- (wrangler --file flag is broken in 4.x, use sqlite3 directly)
-- Remove legacy demo project if present
DELETE FROM projects WHERE id = 'demo-project-1';
-- ─── Customers (from Customers324.csv) ───
@ -87,3 +91,86 @@ INSERT OR IGNORE INTO projects (id, name, status, address, client_name, project_
('proj-n-003', 'N-003-8800-Kelsey', 'ACTIVE', '8800 Rampart Range Rd, Woodland Park, CO', 'Robert Kelsey', 'Daniel M Vogel', '2025-10-15T10:00:00Z'),
('proj-n-004', 'N-004-4200-Auger', 'OPEN', '4200 Teller County Rd, Florissant, CO', 'Chris Auger', 'Wesley Jones', '2026-01-05T08:00:00Z'),
('proj-n-005', 'N-005-6100-Clifford', 'ACTIVE', '6100 High Park Rd, Cripple Creek, CO', 'Joseph Clifford', 'Daniel M Vogel', '2025-11-20T09:00:00Z');
-- ─── Schedule Tasks for N-001-1234-Johnson ───
-- Full construction schedule: preconstruction through closeout
-- As of Jan 2026, project is in drywall phase
INSERT OR IGNORE INTO schedule_tasks (id, project_id, title, start_date, workdays, end_date_calculated, phase, status, is_critical_path, is_milestone, percent_complete, assigned_to, sort_order, created_at, updated_at) VALUES
-- Preconstruction (COMPLETE)
('task-n001-001', 'proj-n-001', 'Permits & Approvals', '2025-08-18', 10, '2025-08-29', 'preconstruction', 'COMPLETE', 1, 0, 100, 'Daniel M Vogel', 1, '2025-08-15T09:00:00Z', '2025-08-29T16:00:00Z'),
('task-n001-002', 'proj-n-001', 'Survey & Staking', '2025-08-25', 3, '2025-08-27', 'preconstruction', 'COMPLETE', 0, 0, 100, 'Colorado Geoscience & Design', 2, '2025-08-15T09:00:00Z', '2025-08-27T15:00:00Z'),
('task-n001-003', 'proj-n-001', 'Soils Report', '2025-08-25', 5, '2025-08-29', 'preconstruction', 'COMPLETE', 0, 0, 100, 'Colorado Geoscience & Design', 3, '2025-08-15T09:00:00Z', '2025-08-29T14:00:00Z'),
-- Sitework (COMPLETE)
('task-n001-004', 'proj-n-001', 'Clear & Grub', '2025-09-02', 3, '2025-09-04', 'sitework', 'COMPLETE', 1, 0, 100, 'Agate Services', 4, '2025-08-15T09:00:00Z', '2025-09-04T16:00:00Z'),
('task-n001-005', 'proj-n-001', 'Rough Grade', '2025-09-05', 5, '2025-09-11', 'sitework', 'COMPLETE', 1, 0, 100, 'Agate Services', 5, '2025-08-15T09:00:00Z', '2025-09-11T16:00:00Z'),
('task-n001-006', 'proj-n-001', 'Driveway Cut & Base', '2025-09-08', 4, '2025-09-11', 'sitework', 'COMPLETE', 0, 0, 100, 'Mule Creek Gravel', 6, '2025-08-15T09:00:00Z', '2025-09-11T16:00:00Z'),
('task-n001-007', 'proj-n-001', 'Utility Trenching', '2025-09-12', 5, '2025-09-18', 'sitework', 'COMPLETE', 1, 0, 100, 'Agate Services', 7, '2025-08-15T09:00:00Z', '2025-09-18T16:00:00Z'),
('task-n001-008', 'proj-n-001', 'Well Drilling', '2025-09-15', 4, '2025-09-18', 'sitework', 'COMPLETE', 0, 0, 100, 'Hamacher Well Works', 8, '2025-08-15T09:00:00Z', '2025-09-18T15:00:00Z'),
-- Foundation (COMPLETE)
('task-n001-009', 'proj-n-001', 'Excavation', '2025-09-22', 3, '2025-09-24', 'foundation', 'COMPLETE', 1, 0, 100, 'Christensen Construction Co. Inc.', 9, '2025-08-15T09:00:00Z', '2025-09-24T16:00:00Z'),
('task-n001-010', 'proj-n-001', 'Pour Footings', '2025-09-25', 5, '2025-10-01', 'foundation', 'COMPLETE', 1, 0, 100, 'Kilgore Companies dba Peak Ready Mix', 10, '2025-08-15T09:00:00Z', '2025-10-01T16:00:00Z'),
('task-n001-011', 'proj-n-001', 'Foundation Walls', '2025-10-02', 7, '2025-10-10', 'foundation', 'COMPLETE', 1, 0, 100, 'Christensen Construction Co. Inc.', 11, '2025-08-15T09:00:00Z', '2025-10-10T16:00:00Z'),
('task-n001-012', 'proj-n-001', 'Waterproofing & Drain Tile', '2025-10-13', 2, '2025-10-14', 'foundation', 'COMPLETE', 0, 0, 100, '1st Priority Home Improvements LLC', 12, '2025-08-15T09:00:00Z', '2025-10-14T16:00:00Z'),
('task-n001-013', 'proj-n-001', 'Backfill', '2025-10-15', 3, '2025-10-17', 'foundation', 'COMPLETE', 1, 0, 100, 'Christensen Construction Co. Inc.', 13, '2025-08-15T09:00:00Z', '2025-10-17T16:00:00Z'),
('task-n001-014', 'proj-n-001', 'Foundation Complete', '2025-10-17', 1, '2025-10-17', 'foundation', 'COMPLETE', 1, 1, 100, NULL, 14, '2025-08-15T09:00:00Z', '2025-10-17T17:00:00Z'),
-- Framing (COMPLETE)
('task-n001-015', 'proj-n-001', 'Floor System', '2025-10-20', 5, '2025-10-24', 'framing', 'COMPLETE', 1, 0, 100, 'Daniel M Vogel', 15, '2025-08-15T09:00:00Z', '2025-10-24T16:00:00Z'),
('task-n001-016', 'proj-n-001', 'Wall Framing', '2025-10-27', 8, '2025-11-05', 'framing', 'COMPLETE', 1, 0, 100, 'Daniel M Vogel', 16, '2025-08-15T09:00:00Z', '2025-11-05T16:00:00Z'),
('task-n001-017', 'proj-n-001', 'Roof Framing', '2025-11-06', 6, '2025-11-13', 'framing', 'COMPLETE', 1, 0, 100, 'Daniel M Vogel', 17, '2025-08-15T09:00:00Z', '2025-11-13T16:00:00Z'),
('task-n001-018', 'proj-n-001', 'Sheathing & Wrap', '2025-11-14', 4, '2025-11-19', 'framing', 'COMPLETE', 1, 0, 100, 'Daniel M Vogel', 18, '2025-08-15T09:00:00Z', '2025-11-19T16:00:00Z'),
('task-n001-019', 'proj-n-001', 'Framing Inspection', '2025-11-20', 1, '2025-11-20', 'framing', 'COMPLETE', 1, 1, 100, 'Daniel M Vogel', 19, '2025-08-15T09:00:00Z', '2025-11-20T12:00:00Z'),
-- Roofing (COMPLETE)
('task-n001-020', 'proj-n-001', 'Roofing Felt & Ice Shield', '2025-11-20', 2, '2025-11-21', 'roofing', 'COMPLETE', 0, 0, 100, 'Simpson Strong-Tie Co Inc', 20, '2025-08-15T09:00:00Z', '2025-11-21T16:00:00Z'),
('task-n001-021', 'proj-n-001', 'Metal Roofing Install', '2025-11-24', 5, '2025-11-28', 'roofing', 'COMPLETE', 1, 0, 100, 'Simpson Strong-Tie Co Inc', 21, '2025-08-15T09:00:00Z', '2025-11-28T16:00:00Z'),
-- Electrical (COMPLETE)
('task-n001-022', 'proj-n-001', 'Rough-In Electrical', '2025-12-01', 6, '2025-12-08', 'electrical', 'COMPLETE', 0, 0, 100, 'Hardrick Enterprises', 22, '2025-08-15T09:00:00Z', '2025-12-08T16:00:00Z'),
-- Plumbing (COMPLETE)
('task-n001-023', 'proj-n-001', 'Rough-In Plumbing', '2025-12-01', 5, '2025-12-05', 'plumbing', 'COMPLETE', 0, 0, 100, 'Teds Plumbing', 23, '2025-08-15T09:00:00Z', '2025-12-05T16:00:00Z'),
-- HVAC (COMPLETE)
('task-n001-024', 'proj-n-001', 'HVAC Rough-In', '2025-12-08', 5, '2025-12-12', 'hvac', 'COMPLETE', 0, 0, 100, 'H2Air of Colorado', 24, '2025-08-15T09:00:00Z', '2025-12-12T16:00:00Z'),
('task-n001-025', 'proj-n-001', 'MEP Inspection', '2025-12-15', 1, '2025-12-15', 'hvac', 'COMPLETE', 1, 1, 100, 'Daniel M Vogel', 25, '2025-08-15T09:00:00Z', '2025-12-15T14:00:00Z'),
-- Insulation (COMPLETE)
('task-n001-026', 'proj-n-001', 'Spray Foam Insulation', '2025-12-16', 4, '2025-12-19', 'insulation', 'COMPLETE', 1, 0, 100, 'Airlite Plastics Co.', 26, '2025-08-15T09:00:00Z', '2025-12-19T16:00:00Z'),
('task-n001-027', 'proj-n-001', 'Batt Insulation', '2025-12-22', 3, '2025-12-24', 'insulation', 'COMPLETE', 0, 0, 100, 'Airlite Plastics Co.', 27, '2025-08-15T09:00:00Z', '2025-12-24T16:00:00Z'),
-- Drywall (IN_PROGRESS)
('task-n001-028', 'proj-n-001', 'Hang Drywall', '2026-01-05', 6, '2026-01-12', 'drywall', 'COMPLETE', 1, 0, 100, 'Advantage Tile Work Inc.', 28, '2025-08-15T09:00:00Z', '2026-01-12T16:00:00Z'),
('task-n001-029', 'proj-n-001', 'Tape & Mud', '2026-01-13', 5, '2026-01-19', 'drywall', 'IN_PROGRESS', 1, 0, 80, 'Advantage Tile Work Inc.', 29, '2025-08-15T09:00:00Z', '2026-01-22T10:00:00Z'),
('task-n001-030', 'proj-n-001', 'Texture & Prime', '2026-01-22', 3, '2026-01-24', 'drywall', 'IN_PROGRESS', 1, 0, 30, 'Advantage Tile Work Inc.', 30, '2025-08-15T09:00:00Z', '2026-01-23T14:00:00Z'),
-- Finish (PENDING)
('task-n001-031', 'proj-n-001', 'Cabinets & Countertops', '2026-01-27', 5, '2026-01-31', 'finish', 'PENDING', 0, 0, 0, NULL, 31, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-032', 'proj-n-001', 'Trim & Millwork', '2026-02-03', 7, '2026-02-11', 'finish', 'PENDING', 0, 0, 0, NULL, 32, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-033', 'proj-n-001', 'Interior Paint', '2026-02-12', 5, '2026-02-18', 'finish', 'PENDING', 1, 0, 0, NULL, 33, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-034', 'proj-n-001', 'Flooring Install', '2026-02-19', 5, '2026-02-25', 'finish', 'PENDING', 0, 0, 0, NULL, 34, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-035', 'proj-n-001', 'Fixtures & Hardware', '2026-02-26', 3, '2026-02-28', 'finish', 'PENDING', 0, 0, 0, NULL, 35, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-036', 'proj-n-001', 'Final Electrical & Plumbing', '2026-03-02', 3, '2026-03-04', 'finish', 'PENDING', 0, 0, 0, NULL, 36, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
-- Landscaping (PENDING)
('task-n001-037', 'proj-n-001', 'Final Grade', '2026-03-05', 3, '2026-03-09', 'landscaping', 'PENDING', 0, 0, 0, NULL, 37, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-038', 'proj-n-001', 'Landscaping & Seed', '2026-03-10', 4, '2026-03-13', 'landscaping', 'PENDING', 0, 0, 0, NULL, 38, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
-- Closeout (PENDING)
('task-n001-039', 'proj-n-001', 'Final Inspections', '2026-03-16', 3, '2026-03-18', 'closeout', 'PENDING', 1, 0, 0, 'Daniel M Vogel', 39, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-040', 'proj-n-001', 'Punch List', '2026-03-19', 5, '2026-03-25', 'closeout', 'PENDING', 0, 0, 0, NULL, 40, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z'),
('task-n001-041', 'proj-n-001', 'Certificate of Occupancy', '2026-03-26', 2, '2026-03-27', 'closeout', 'PENDING', 1, 1, 0, 'Daniel M Vogel', 41, '2025-08-15T09:00:00Z', '2025-08-15T09:00:00Z');
-- ─── Dependencies for N-001 (finish-to-start) ───
INSERT OR IGNORE INTO task_dependencies (id, predecessor_id, successor_id, type, lag_days) VALUES
('dep-n001-01', 'task-n001-001', 'task-n001-004', 'FS', 0),
('dep-n001-02', 'task-n001-007', 'task-n001-009', 'FS', 2),
('dep-n001-03', 'task-n001-010', 'task-n001-011', 'FS', 0),
('dep-n001-04', 'task-n001-011', 'task-n001-012', 'FS', 0),
('dep-n001-05', 'task-n001-013', 'task-n001-015', 'FS', 1),
('dep-n001-06', 'task-n001-018', 'task-n001-020', 'FS', 0),
('dep-n001-07', 'task-n001-019', 'task-n001-022', 'FS', 0),
('dep-n001-08', 'task-n001-019', 'task-n001-023', 'FS', 0),
('dep-n001-09', 'task-n001-024', 'task-n001-025', 'FS', 0),
('dep-n001-10', 'task-n001-025', 'task-n001-026', 'FS', 0),
('dep-n001-11', 'task-n001-027', 'task-n001-028', 'FS', 0),
('dep-n001-12', 'task-n001-028', 'task-n001-029', 'FS', 0),
('dep-n001-13', 'task-n001-029', 'task-n001-030', 'FS', 0),
('dep-n001-14', 'task-n001-030', 'task-n001-031', 'FS', 1),
('dep-n001-15', 'task-n001-035', 'task-n001-036', 'FS', 0),
('dep-n001-16', 'task-n001-036', 'task-n001-037', 'FS', 0),
('dep-n001-17', 'task-n001-038', 'task-n001-039', 'FS', 1),
('dep-n001-18', 'task-n001-039', 'task-n001-040', 'FS', 0),
('dep-n001-19', 'task-n001-040', 'task-n001-041', 'FS', 0);

View File

@ -1,56 +1,33 @@
import Link from "next/link"
import { getCloudflareContext } from "@opennextjs/cloudflare"
import { getDb } from "@/db"
import { projects } from "@/db/schema"
import { IconCalendarStats, IconFolder } from "@tabler/icons-react"
import { asc } from "drizzle-orm"
import { redirect } from "next/navigation"
import { IconFolder } from "@tabler/icons-react"
export default async function ProjectsPage() {
const { env } = await getCloudflareContext()
const db = getDb(env.DB)
const allProjects = await db.select().from(projects)
try {
const { env } = await getCloudflareContext()
if (!env?.DB) throw new Error("D1 not available")
const db = getDb(env.DB)
const [first] = await db
.select({ id: projects.id })
.from(projects)
.orderBy(asc(projects.name))
.limit(1)
if (first) redirect(`/dashboard/projects/${first.id}`)
} catch (e) {
if (e && typeof e === "object" && "digest" in e) throw e
}
return (
<div className="p-6">
<div className="flex items-center justify-between mb-6">
<h1 className="text-2xl font-semibold">Projects</h1>
<div className="flex flex-1 items-center justify-center text-center text-muted-foreground">
<div>
<IconFolder className="mx-auto mb-4 size-12 opacity-50" />
<p>No projects yet.</p>
</div>
{allProjects.length === 0 ? (
<div className="text-center py-12 text-muted-foreground">
<IconFolder className="mx-auto mb-4 size-12 opacity-50" />
<p>No projects yet.</p>
<p className="text-sm mt-1">
Create a D1 database and seed a demo project to get started.
</p>
</div>
) : (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{allProjects.map((project) => (
<div
key={project.id}
className="rounded-lg border p-4"
>
<div className="flex items-center gap-3 mb-3">
<IconFolder className="size-5 text-muted-foreground" />
<div>
<p className="font-medium">{project.name}</p>
<p className="text-sm text-muted-foreground">
Created{" "}
{new Date(project.createdAt).toLocaleDateString()}
</p>
</div>
</div>
<Link
href={`/dashboard/projects/${project.id}/schedule`}
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
<IconCalendarStats className="size-4" />
Schedule
</Link>
</div>
))}
</div>
)}
</div>
)
}