feat: Add project type and status fields to project forms and views, including database migrations

This commit is contained in:
Chop
2025-06-04 22:53:33 +02:00
parent e136c9f0e8
commit 49d49b42f1
6 changed files with 138 additions and 6 deletions

View File

@@ -12,8 +12,8 @@ import { differenceInCalendarDays, parseISO } from "date-fns";
import PageContainer from "@/components/ui/PageContainer";
import PageHeader from "@/components/ui/PageHeader";
export default async function ProjectViewPage({ params }) {
const { id } = await params;
export default function ProjectViewPage({ params }) {
const { id } = params;
const project = getProjectWithContract(id);
const notes = getNotesForProject(id);
const daysRemaining = differenceInCalendarDays(
@@ -141,6 +141,36 @@ export default async function ProjectViewPage({ params }) {
<p className="text-gray-900">{project.notes}</p>
</div>
)}
<div>
<span className="text-sm font-medium text-gray-500">
Typ projektu
</span>
<p className="text-gray-900">
{project.project_type === "design"
? "Projektowanie"
: project.project_type === "construction"
? "Realizacja"
: project.project_type === "design+construction"
? "Projektowanie + Realizacja"
: "-"}
</p>
</div>
<div>
<span className="text-sm font-medium text-gray-500">
Status projektu
</span>
<p className="text-gray-900">
{project.project_status === "registered"
? "Zarejestrowany"
: project.project_status === "in_progress_design"
? "W realizacji (projektowanie)"
: project.project_status === "in_progress_construction"
? "W realizacji (realizacja)"
: project.project_status === "fulfilled"
? "Zakończony"
: "-"}
</p>
</div>
</CardContent>
</Card>
<Card>

View File

@@ -192,6 +192,26 @@ export default function ProjectListPage() {
<div className="col-span-1 text-sm text-gray-600 truncate">
{project.finish_date || "N/A"}
</div>
<div className="col-span-1 text-sm text-gray-600 truncate">
{project.project_type === "design"
? "Projektowanie"
: project.project_type === "construction"
? "Realizacja"
: project.project_type === "design+construction"
? "Projektowanie + Realizacja"
: "-"}
</div>
<div className="col-span-1 text-sm text-gray-600 truncate">
{project.project_status === "registered"
? "Zarejestrowany"
: project.project_status === "in_progress_design"
? "W realizacji (projektowanie)"
: project.project_status === "in_progress_construction"
? "W realizacji (realizacja)"
: project.project_status === "fulfilled"
? "Zakończony"
: "-"}
</div>
<div className="col-span-1">
<Link href={`/projects/${project.project_id}`}>
<Button variant="outline" size="sm">

View File

@@ -17,6 +17,8 @@ export default function ProjectForm({ initialData = null }) {
wp: "",
contact: "",
notes: "",
project_type: initialData?.project_type || "design",
// project_status is not included in the form for creation or editing
...initialData,
});
@@ -74,6 +76,24 @@ export default function ProjectForm({ initialData = null }) {
</select>
</div>
{/* Project Type Dropdown */}
<div>
<label className="block font-medium">Typ projektu</label>
<select
name="project_type"
value={form.project_type}
onChange={handleChange}
className="border p-2 w-full"
required
>
<option value="design">Projektowanie</option>
<option value="construction">Realizacja</option>
<option value="design+construction">
Projektowanie + Realizacja
</option>
</select>
</div>
{/* Other fields */}
{[
["project_name", "Nazwa projektu"],

View File

@@ -0,0 +1,38 @@
"use client";
import { useState } from "react";
export default function ProjectStatusDropdown({ project, onStatusChange }) {
const [status, setStatus] = useState(project.project_status);
const [loading, setLoading] = useState(false);
const handleChange = async (e) => {
const newStatus = e.target.value;
setStatus(newStatus);
setLoading(true);
await fetch(`/api/projects/${project.project_id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...project, project_status: newStatus }),
});
setLoading(false);
if (onStatusChange) onStatusChange(newStatus);
};
return (
<select
name="project_status"
value={status}
onChange={handleChange}
className="ml-2 border p-1 rounded"
disabled={loading}
>
<option value="registered">Zarejestrowany</option>
<option value="in_progress_design">W realizacji (projektowanie)</option>
<option value="in_progress_construction">
W realizacji (realizacja)
</option>
<option value="fulfilled">Zakończony</option>
</select>
);
}

View File

@@ -30,6 +30,8 @@ export default function initializeDatabase() {
wp TEXT,
contact TEXT,
notes TEXT,
project_type TEXT CHECK(project_type IN ('design', 'construction', 'design+construction')) DEFAULT 'design',
project_status TEXT CHECK(project_status IN ('registered', 'in_progress_design', 'in_progress_construction', 'fulfilled')) DEFAULT 'registered',
FOREIGN KEY (contract_id) REFERENCES contracts(contract_id)
);
@@ -98,4 +100,22 @@ export default function initializeDatabase() {
} catch (e) {
// Column already exists, ignore error
}
// Migration: Add project_type column to projects table
try {
db.exec(`
ALTER TABLE projects ADD COLUMN project_type TEXT CHECK(project_type IN ('design', 'construction', 'design+construction')) DEFAULT 'design';
`);
} catch (e) {
// Column already exists, ignore error
}
// Migration: Add project_status column to projects table
try {
db.exec(`
ALTER TABLE projects ADD COLUMN project_status TEXT CHECK(project_status IN ('registered', 'in_progress_design', 'in_progress_construction', 'fulfilled')) DEFAULT 'registered';
`);
} catch (e) {
// Column already exists, ignore error
}
}

View File

@@ -42,8 +42,8 @@ export function createProject(data) {
const stmt = db.prepare(`
INSERT INTO projects (
contract_id, project_name, project_number, address, plot, district, unit, city, investment_number, finish_date,
wp, contact, notes
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
wp, contact, notes, project_type, project_status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(
data.contract_id,
@@ -58,7 +58,9 @@ export function createProject(data) {
data.finish_date,
data.wp,
data.contact,
data.notes
data.notes,
data.project_type || "design",
data.project_status || "registered"
);
}
@@ -66,7 +68,7 @@ export function updateProject(id, data) {
const stmt = db.prepare(`
UPDATE projects SET
contract_id = ?, project_name = ?, project_number = ?, address = ?, plot = ?, district = ?, unit = ?, city = ?,
investment_number = ?, finish_date = ?, wp = ?, contact = ?, notes = ?
investment_number = ?, finish_date = ?, wp = ?, contact = ?, notes = ?, project_type = ?, project_status = ?
WHERE project_id = ?
`);
stmt.run(
@@ -83,6 +85,8 @@ export function updateProject(id, data) {
data.wp,
data.contact,
data.notes,
data.project_type || "design",
data.project_status || "registered",
id
);
}