feat: Add coordinate formatting utility and update project views
This commit is contained in:
@@ -9,7 +9,7 @@ import Button from "@/components/ui/Button";
|
|||||||
import Badge from "@/components/ui/Badge";
|
import Badge from "@/components/ui/Badge";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { differenceInCalendarDays, parseISO } from "date-fns";
|
import { differenceInCalendarDays, parseISO } from "date-fns";
|
||||||
import { formatDate } from "@/lib/utils";
|
import { formatDate, formatCoordinates } from "@/lib/utils";
|
||||||
import PageContainer from "@/components/ui/PageContainer";
|
import PageContainer from "@/components/ui/PageContainer";
|
||||||
import PageHeader from "@/components/ui/PageHeader";
|
import PageHeader from "@/components/ui/PageHeader";
|
||||||
import ProjectStatusDropdown from "@/components/ProjectStatusDropdown";
|
import ProjectStatusDropdown from "@/components/ProjectStatusDropdown";
|
||||||
@@ -217,7 +217,7 @@ export default async function ProjectViewPage({ params }) {
|
|||||||
Coordinates
|
Coordinates
|
||||||
</span>
|
</span>
|
||||||
<p className="text-gray-900 font-medium font-mono text-sm">
|
<p className="text-gray-900 font-medium font-mono text-sm">
|
||||||
{project.coordinates}
|
{formatCoordinates(project.coordinates)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -196,12 +196,6 @@ export default function ProjectListPage() {
|
|||||||
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-24">
|
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-24">
|
||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-24">
|
|
||||||
Created By
|
|
||||||
</th>
|
|
||||||
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-24">
|
|
||||||
Assigned To
|
|
||||||
</th>
|
|
||||||
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-20">
|
<th className="text-left px-2 py-3 font-semibold text-xs text-gray-700 w-20">
|
||||||
Actions
|
Actions
|
||||||
</th>
|
</th>
|
||||||
@@ -281,18 +275,6 @@ export default function ProjectListPage() {
|
|||||||
? "Zakończony"
|
? "Zakończony"
|
||||||
: "-"}
|
: "-"}
|
||||||
</td>
|
</td>
|
||||||
<td
|
|
||||||
className="px-2 py-3 text-xs text-gray-600 truncate"
|
|
||||||
title={project.created_by_name || "Unknown"}
|
|
||||||
>
|
|
||||||
{project.created_by_name || "Unknown"}
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
className="px-2 py-3 text-xs text-gray-600 truncate"
|
|
||||||
title={project.assigned_to_name || "Unassigned"}
|
|
||||||
>
|
|
||||||
{project.assigned_to_name || "Unassigned"}
|
|
||||||
</td>
|
|
||||||
<td className="px-2 py-3">
|
<td className="px-2 py-3">
|
||||||
<Link href={`/projects/${project.project_id}`}>
|
<Link href={`/projects/${project.project_id}`}>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -73,9 +73,6 @@ export default function ProjectStatusDropdown({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleOpen = () => {
|
const handleOpen = () => {
|
||||||
console.log(
|
|
||||||
"ProjectStatusDropdown handleOpen called, setting isOpen to true"
|
|
||||||
);
|
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,10 +108,6 @@ export default function ProjectStatusDropdown({
|
|||||||
<button
|
<button
|
||||||
ref={buttonRef}
|
ref={buttonRef}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(
|
|
||||||
"ProjectStatusDropdown button clicked, current isOpen:",
|
|
||||||
isOpen
|
|
||||||
);
|
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
}}
|
}}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
@@ -145,17 +138,13 @@ export default function ProjectStatusDropdown({
|
|||||||
</svg>
|
</svg>
|
||||||
</Badge>
|
</Badge>
|
||||||
</button>{" "}
|
</button>{" "}
|
||||||
{/* Simple dropdown for debugging */}
|
{/* Status Options Dropdown */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="absolute top-full left-0 mt-1 bg-white border-2 border-red-500 rounded-md shadow-lg z-[9999] min-w-[140px]">
|
<div className="absolute top-full left-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-[9999] min-w-[140px]">
|
||||||
<div className="bg-yellow-100 p-2 text-xs text-center border-b">
|
|
||||||
DEBUG: ProjectStatus Dropdown is visible
|
|
||||||
</div>
|
|
||||||
{Object.entries(statusConfig).map(([statusKey, config]) => (
|
{Object.entries(statusConfig).map(([statusKey, config]) => (
|
||||||
<button
|
<button
|
||||||
key={statusKey}
|
key={statusKey}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("ProjectStatus Option clicked:", statusKey);
|
|
||||||
handleChange(statusKey);
|
handleChange(statusKey);
|
||||||
}}
|
}}
|
||||||
className="w-full text-left px-3 py-2 hover:bg-gray-50 transition-colors first:rounded-t-md last:rounded-b-md"
|
className="w-full text-left px-3 py-2 hover:bg-gray-50 transition-colors first:rounded-t-md last:rounded-b-md"
|
||||||
@@ -170,9 +159,8 @@ export default function ProjectStatusDropdown({
|
|||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-[9998] bg-black bg-opacity-10"
|
className="fixed inset-0 z-[9998]"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("ProjectStatus Backdrop clicked");
|
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -88,3 +88,42 @@ export const formatDateForInput = (date) => {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatCoordinates = (coordinatesString) => {
|
||||||
|
if (!coordinatesString) return "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [latStr, lngStr] = coordinatesString.split(",");
|
||||||
|
const lat = parseFloat(latStr.trim());
|
||||||
|
const lng = parseFloat(lngStr.trim());
|
||||||
|
|
||||||
|
if (isNaN(lat) || isNaN(lng)) {
|
||||||
|
return coordinatesString; // Return original if parsing fails
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDMS = (decimal, isLatitude) => {
|
||||||
|
const direction = isLatitude
|
||||||
|
? decimal >= 0
|
||||||
|
? "N"
|
||||||
|
: "S"
|
||||||
|
: decimal >= 0
|
||||||
|
? "E"
|
||||||
|
: "W";
|
||||||
|
|
||||||
|
const absolute = Math.abs(decimal);
|
||||||
|
const degrees = Math.floor(absolute);
|
||||||
|
const minutes = Math.floor((absolute - degrees) * 60);
|
||||||
|
const seconds = Math.round(((absolute - degrees) * 60 - minutes) * 60);
|
||||||
|
|
||||||
|
return `${direction}: ${degrees}°${minutes}'${seconds}"`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const latDMS = formatDMS(lat, true);
|
||||||
|
const lngDMS = formatDMS(lng, false);
|
||||||
|
|
||||||
|
return `${latDMS}, ${lngDMS}`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error formatting coordinates:", error);
|
||||||
|
return coordinatesString;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user