From 639179ed2144b7c017fbfb007764eddecaddf888 Mon Sep 17 00:00:00 2001 From: Chop <28534054+RChopin@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:29:06 +0200 Subject: [PATCH] feat: Add date formatting utility functions and integrate them across components --- src/app/contracts/[id]/page.js | 23 ++--- src/app/contracts/page.js | 13 ++- src/app/page.js | 5 +- src/app/projects/[id]/page.js | 7 +- src/app/projects/page.js | 7 +- src/app/tasks/page.js | 1 + src/components/ContractForm.js | 9 +- src/components/ProjectForm.js | 5 +- src/components/ProjectTasksDashboard.js | 1 + src/components/ProjectTasksSection.js | 15 ++-- src/lib/utils.js | 106 +++++++++++++++++------- 11 files changed, 118 insertions(+), 74 deletions(-) diff --git a/src/app/contracts/[id]/page.js b/src/app/contracts/[id]/page.js index 6685671..f6ad64d 100644 --- a/src/app/contracts/[id]/page.js +++ b/src/app/contracts/[id]/page.js @@ -9,6 +9,7 @@ import Badge from "@/components/ui/Badge"; import PageContainer from "@/components/ui/PageContainer"; import PageHeader from "@/components/ui/PageHeader"; import { LoadingState } from "@/components/ui/States"; +import { formatDate } from "@/lib/utils"; export default function ContractDetailsPage() { const params = useParams(); @@ -135,7 +136,6 @@ export default function ContractDetailsPage() { {contract.contract_number}

- {contract.contract_name && (
@@ -146,7 +146,6 @@ export default function ContractDetailsPage() {

)} - {contract.customer_contract_number && (
@@ -157,7 +156,6 @@ export default function ContractDetailsPage() {

)} - {contract.customer && (
@@ -168,7 +166,6 @@ export default function ContractDetailsPage() {

)} - {contract.investor && (
@@ -178,30 +175,24 @@ export default function ContractDetailsPage() { {contract.investor}

- )} - + )}{" "} {contract.date_signed && (
Date Signed

- {new Date(contract.date_signed).toLocaleDateString( - "en-US" - )} + {formatDate(contract.date_signed)}

)} - {contract.finish_date && (
Finish Date

- {new Date(contract.finish_date).toLocaleDateString( - "en-US" - )} + {formatDate(contract.finish_date)}

)} @@ -350,10 +341,8 @@ export default function ContractDetailsPage() { d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clipRule="evenodd" /> - - {new Date(project.finish_date).toLocaleDateString( - "en-US" - )} + {" "} + {formatDate(project.finish_date)} )}
diff --git a/src/app/contracts/page.js b/src/app/contracts/page.js index ed221e0..392fbeb 100644 --- a/src/app/contracts/page.js +++ b/src/app/contracts/page.js @@ -10,6 +10,7 @@ import PageHeader from "@/components/ui/PageHeader"; import SearchBar from "@/components/ui/SearchBar"; import FilterBar from "@/components/ui/FilterBar"; import { LoadingState } from "@/components/ui/States"; +import { formatDate } from "@/lib/utils"; export default function ContractsMainPage() { const [contracts, setContracts] = useState([]); @@ -485,11 +486,9 @@ export default function ContractsMainPage() { Zawarcie: - + {" "} - {new Date( - contract.date_signed - ).toLocaleDateString("pl-PL")} + {formatDate(contract.date_signed)}
)} @@ -510,11 +509,9 @@ export default function ContractsMainPage() { Zakończenie: - + {" "} - {new Date( - contract.finish_date - ).toLocaleDateString("pl-PL")} + {formatDate(contract.finish_date)} )} diff --git a/src/app/page.js b/src/app/page.js index 602226e..7bae139 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -20,6 +20,7 @@ import { endOfWeek, format, } from "date-fns"; +import { formatDate } from "@/lib/utils"; export default function Home() { const [stats, setStats] = useState({ @@ -767,7 +768,7 @@ export default function Home() { {deadline.type === "project" ? deadline.city : deadline.customer}{" "} - • {deadline.date} + • {formatDate(deadline.date)}

@@ -839,7 +840,7 @@ export default function Home() { {project.finish_date && (

- Due: {project.finish_date} + Due: {formatDate(project.finish_date)}

)} diff --git a/src/app/projects/[id]/page.js b/src/app/projects/[id]/page.js index 868904c..dadcc4b 100644 --- a/src/app/projects/[id]/page.js +++ b/src/app/projects/[id]/page.js @@ -9,6 +9,7 @@ import Button from "@/components/ui/Button"; import Badge from "@/components/ui/Badge"; import Link from "next/link"; import { differenceInCalendarDays, parseISO } from "date-fns"; +import { formatDate } from "@/lib/utils"; import PageContainer from "@/components/ui/PageContainer"; import PageHeader from "@/components/ui/PageHeader"; import ProjectStatusDropdown from "@/components/ProjectStatusDropdown"; @@ -172,13 +173,15 @@ export default async function ProjectViewPage({ params }) {

{project.unit || "N/A"}

- + {" "}
Deadline

- {project.finish_date || "N/A"} + {project.finish_date + ? formatDate(project.finish_date) + : "N/A"}

diff --git a/src/app/projects/page.js b/src/app/projects/page.js index 9a7be3e..d18030f 100644 --- a/src/app/projects/page.js +++ b/src/app/projects/page.js @@ -10,6 +10,7 @@ import PageContainer from "@/components/ui/PageContainer"; import PageHeader from "@/components/ui/PageHeader"; import SearchBar from "@/components/ui/SearchBar"; import { LoadingState } from "@/components/ui/States"; +import { formatDate } from "@/lib/utils"; export default function ProjectListPage() { const [projects, setProjects] = useState([]); @@ -245,12 +246,14 @@ export default function ProjectListPage() { title={project.plot} > {project.plot || "N/A"} - + {" "} - {project.finish_date || "N/A"} + {project.finish_date + ? formatDate(project.finish_date) + : "N/A"} {project.project_type === "design" diff --git a/src/app/tasks/page.js b/src/app/tasks/page.js index bd6689e..7ab24d1 100644 --- a/src/app/tasks/page.js +++ b/src/app/tasks/page.js @@ -8,6 +8,7 @@ import Badge from "@/components/ui/Badge"; import TaskStatusDropdownSimple from "@/components/TaskStatusDropdownSimple"; import { Input } from "@/components/ui/Input"; import { formatDistanceToNow, parseISO } from "date-fns"; +import { formatDate } from "@/lib/utils"; import PageContainer from "@/components/ui/PageContainer"; import PageHeader from "@/components/ui/PageHeader"; import SearchBar from "@/components/ui/SearchBar"; diff --git a/src/components/ContractForm.js b/src/components/ContractForm.js index 5d12dd4..bf4eee6 100644 --- a/src/components/ContractForm.js +++ b/src/components/ContractForm.js @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import { Card, CardHeader, CardContent } from "@/components/ui/Card"; import Button from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; +import { formatDateForInput } from "@/lib/utils"; export default function ContractForm() { const [form, setForm] = useState({ @@ -133,11 +134,11 @@ export default function ContractForm() {
+ {" "}
@@ -145,11 +146,11 @@ export default function ContractForm() {
+ {" "}
diff --git a/src/components/ProjectForm.js b/src/components/ProjectForm.js index abc66ec..4034b5e 100644 --- a/src/components/ProjectForm.js +++ b/src/components/ProjectForm.js @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import { Card, CardHeader, CardContent } from "@/components/ui/Card"; import Button from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; +import { formatDateForInput } from "@/lib/utils"; export default function ProjectForm({ initialData = null }) { const [form, setForm] = useState({ @@ -214,11 +215,11 @@ export default function ProjectForm({ initialData = null }) {
+ {" "}
diff --git a/src/components/ProjectTasksDashboard.js b/src/components/ProjectTasksDashboard.js index ea4e2a0..513c703 100644 --- a/src/components/ProjectTasksDashboard.js +++ b/src/components/ProjectTasksDashboard.js @@ -13,6 +13,7 @@ import { parseISO, formatDistanceToNow, } from "date-fns"; +import { formatDate } from "@/lib/utils"; export default function ProjectTasksDashboard() { const [allTasks, setAllTasks] = useState([]); diff --git a/src/components/ProjectTasksSection.js b/src/components/ProjectTasksSection.js index 40e2d79..5692e99 100644 --- a/src/components/ProjectTasksSection.js +++ b/src/components/ProjectTasksSection.js @@ -6,6 +6,7 @@ import TaskStatusDropdownSimple from "./TaskStatusDropdownSimple"; import { Card, CardHeader, CardContent } from "./ui/Card"; import Button from "./ui/Button"; import Badge from "./ui/Badge"; +import { formatDate } from "@/lib/utils"; export default function ProjectTasksSection({ projectId }) { const [projectTasks, setProjectTasks] = useState([]); @@ -444,7 +445,7 @@ export default function ProjectTasksSection({ projectId }) { {" "} {task.date_started - ? new Date(task.date_started).toLocaleDateString() + ? formatDate(task.date_started) : "Not started"} {" "} @@ -519,15 +520,11 @@ export default function ProjectTasksSection({ projectId }) {

{note.note} -

+

{" "}

- {new Date( - note.note_date - ).toLocaleDateString()}{" "} - at{" "} - {new Date( - note.note_date - ).toLocaleTimeString()} + {formatDate(note.note_date, { + includeTime: true, + })}

{!note.is_system && ( diff --git a/src/lib/utils.js b/src/lib/utils.js index 4800018..12d3db7 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,40 +1,90 @@ // Test utilities for deadline and status formatting export const getDeadlineVariant = (days) => { - if (days < 0) return "danger"; - if (days <= 7) return "warning"; - return "success"; + if (days < 0) return "danger"; + if (days <= 7) return "warning"; + return "success"; }; export const formatProjectStatus = (status) => { - switch (status) { - case "registered": - return "Zarejestrowany"; - case "in_progress_design": - return "W realizacji (projektowanie)"; - case "in_progress_construction": - return "W realizacji (realizacja)"; - case "fulfilled": - return "Zakończony"; - default: - return "-"; - } + switch (status) { + case "registered": + return "Zarejestrowany"; + case "in_progress_design": + return "W realizacji (projektowanie)"; + case "in_progress_construction": + return "W realizacji (realizacja)"; + case "fulfilled": + return "Zakończony"; + default: + return "-"; + } }; export const formatProjectType = (type) => { - switch (type) { - case "design": - return "Projektowanie"; - case "construction": - return "Realizacja"; - case "design+construction": - return "Projektowanie + Realizacja"; - default: - return "-"; - } + switch (type) { + case "design": + return "Projektowanie"; + case "construction": + return "Realizacja"; + case "design+construction": + return "Projektowanie + Realizacja"; + default: + return "-"; + } }; export const getDeadlineText = (daysRemaining) => { - if (daysRemaining === 0) return "Due Today"; - if (daysRemaining > 0) return `${daysRemaining} days left`; - return `${Math.abs(daysRemaining)} days overdue`; + if (daysRemaining === 0) return "Due Today"; + if (daysRemaining > 0) return `${daysRemaining} days left`; + return `${Math.abs(daysRemaining)} days overdue`; +}; + +export const formatDate = (date, options = {}) => { + if (!date) return ""; + + try { + const dateObj = typeof date === "string" ? new Date(date) : date; + + if (isNaN(dateObj.getTime())) { + return "Invalid date"; + } + + // Default to DD.MM.YYYY format + const day = String(dateObj.getDate()).padStart(2, "0"); + const month = String(dateObj.getMonth() + 1).padStart(2, "0"); + const year = dateObj.getFullYear(); + + if (options.includeTime) { + const hours = String(dateObj.getHours()).padStart(2, "0"); + const minutes = String(dateObj.getMinutes()).padStart(2, "0"); + return `${day}.${month}.${year} ${hours}:${minutes}`; + } + + return `${day}.${month}.${year}`; + } catch (error) { + console.error("Error formatting date:", error); + return "Invalid date"; + } +}; + +export const formatDateForInput = (date) => { + if (!date) return ""; + + try { + const dateObj = typeof date === "string" ? new Date(date) : date; + + if (isNaN(dateObj.getTime())) { + return ""; + } + + // Format as YYYY-MM-DD for HTML date inputs + const year = dateObj.getFullYear(); + const month = String(dateObj.getMonth() + 1).padStart(2, "0"); + const day = String(dateObj.getDate()).padStart(2, "0"); + + return `${year}-${month}-${day}`; + } catch (error) { + console.error("Error formatting date for input:", error); + return ""; + } };