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 Link from "next/link";
|
||||
import { differenceInCalendarDays, parseISO } from "date-fns";
|
||||
import { formatDate } from "@/lib/utils";
|
||||
import { formatDate, formatCoordinates } from "@/lib/utils";
|
||||
import PageContainer from "@/components/ui/PageContainer";
|
||||
import PageHeader from "@/components/ui/PageHeader";
|
||||
import ProjectStatusDropdown from "@/components/ProjectStatusDropdown";
|
||||
@@ -217,7 +217,7 @@ export default async function ProjectViewPage({ params }) {
|
||||
Coordinates
|
||||
</span>
|
||||
<p className="text-gray-900 font-medium font-mono text-sm">
|
||||
{project.coordinates}
|
||||
{formatCoordinates(project.coordinates)}
|
||||
</p>
|
||||
</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">
|
||||
Status
|
||||
</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">
|
||||
Actions
|
||||
</th>
|
||||
@@ -281,18 +275,6 @@ export default function ProjectListPage() {
|
||||
? "Zakończony"
|
||||
: "-"}
|
||||
</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">
|
||||
<Link href={`/projects/${project.project_id}`}>
|
||||
<Button
|
||||
|
||||
@@ -73,9 +73,6 @@ export default function ProjectStatusDropdown({
|
||||
}
|
||||
};
|
||||
const handleOpen = () => {
|
||||
console.log(
|
||||
"ProjectStatusDropdown handleOpen called, setting isOpen to true"
|
||||
);
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
@@ -111,10 +108,6 @@ export default function ProjectStatusDropdown({
|
||||
<button
|
||||
ref={buttonRef}
|
||||
onClick={() => {
|
||||
console.log(
|
||||
"ProjectStatusDropdown button clicked, current isOpen:",
|
||||
isOpen
|
||||
);
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
disabled={loading}
|
||||
@@ -145,17 +138,13 @@ export default function ProjectStatusDropdown({
|
||||
</svg>
|
||||
</Badge>
|
||||
</button>{" "}
|
||||
{/* Simple dropdown for debugging */}
|
||||
{/* Status Options Dropdown */}
|
||||
{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="bg-yellow-100 p-2 text-xs text-center border-b">
|
||||
DEBUG: ProjectStatus Dropdown is visible
|
||||
</div>
|
||||
<div className="absolute top-full left-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-[9999] min-w-[140px]">
|
||||
{Object.entries(statusConfig).map(([statusKey, config]) => (
|
||||
<button
|
||||
key={statusKey}
|
||||
onClick={() => {
|
||||
console.log("ProjectStatus Option clicked:", 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"
|
||||
@@ -170,9 +159,8 @@ export default function ProjectStatusDropdown({
|
||||
{/* Backdrop */}
|
||||
{isOpen && (
|
||||
<div
|
||||
className="fixed inset-0 z-[9998] bg-black bg-opacity-10"
|
||||
className="fixed inset-0 z-[9998]"
|
||||
onClick={() => {
|
||||
console.log("ProjectStatus Backdrop clicked");
|
||||
setIsOpen(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -88,3 +88,42 @@ export const formatDateForInput = (date) => {
|
||||
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