diff --git a/src/app/globals.css b/src/app/globals.css
index 53d3763..c835955 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -263,6 +263,10 @@
@apply text-sm text-brand-l leading-relaxed;
}
+.card-loading {
+ @apply opacity-60 pointer-events-none animate-pulse;
+}
+
/* Card Grid System */
.card-grid {
@apply grid gap-6;
@@ -980,6 +984,28 @@ select:disabled {
}
}
+/* Location buttons within service listings */
+.location-btn {
+ background-color: var(--color-brand-q);
+ border-color: #e5e7eb;
+ color: var(--color-brand-l);
+ cursor: pointer;
+}
+
+.location-btn:hover {
+ background-color: #e9e9e9;
+ border-color: var(--color-brand-f);
+}
+
+.location-btn.selected {
+ border-color: var(--color-brand-a);
+ color: var(--color-brand-k);
+}
+
+.location-btn.selected:hover {
+ background-color: #e6f5f1;
+}
+
/* Statistics section */
.statistics-value {
font-family: 'Museo Sans', Arial, sans-serif;
diff --git a/src/components/FindHelp/GroupedServiceCard.tsx b/src/components/FindHelp/GroupedServiceCard.tsx
index 70820a5..7d5556c 100644
--- a/src/components/FindHelp/GroupedServiceCard.tsx
+++ b/src/components/FindHelp/GroupedServiceCard.tsx
@@ -1,6 +1,6 @@
'use client';
-import React from 'react';
+import React, { useState } from 'react';
import Link from 'next/link';
import { useSearchParams } from 'next/navigation';
import { useLocation } from '@/contexts/LocationContext';
@@ -90,10 +90,13 @@ const GroupedServiceCard = React.memo(function GroupedServiceCard({
const shouldTruncate = decodedDescription.length > 100;
+ const [isLoading, setIsLoading] = useState(false);
+
return (
setIsLoading(true)}
+ className={`card card-compact${isLoading ? ' card-loading' : ''}`}
aria-label={`View details for ${decodedOrgName}`}
>
diff --git a/src/components/FindHelp/ServiceCard.tsx b/src/components/FindHelp/ServiceCard.tsx
index 615443e..fea05ff 100644
--- a/src/components/FindHelp/ServiceCard.tsx
+++ b/src/components/FindHelp/ServiceCard.tsx
@@ -1,6 +1,6 @@
'use client';
-import React, { useMemo } from 'react';
+import React, { useMemo, useState } from 'react';
import Link from 'next/link';
import { useSearchParams } from 'next/navigation';
import { useLocation } from '@/contexts/LocationContext';
@@ -70,6 +70,12 @@ const ServiceCard = React.memo(function ServiceCard({ service, isOpen, onToggle
const distanceText = formatDistance(service.distance);
+ const is24Hour = service.isOpen247 || (service.openTimes && service.openTimes.some((slot) => {
+ const startTime = Number(slot.start);
+ const endTime = Number(slot.end);
+ return startTime === 0 && endTime === 2359;
+ }));
+
return {
destination,
decodedDescription,
@@ -81,7 +87,8 @@ const ServiceCard = React.memo(function ServiceCard({ service, isOpen, onToggle
categoryName,
subCategoryName,
openingStatus,
- distanceText
+ distanceText,
+ is24Hour
};
}, [service, location, searchParams]);
@@ -93,21 +100,24 @@ const ServiceCard = React.memo(function ServiceCard({ service, isOpen, onToggle
categoryName,
subCategoryName,
openingStatus,
- distanceText
+ distanceText,
+ is24Hour
} = memoizedData;
+ const [isLoading, setIsLoading] = useState(false);
+
return (
{
- // Track service card click for analytics
+ setIsLoading(true);
trackServiceCardClick(
service.id?.toString() || 'unknown',
decodedOrgName,
categoryName
);
}}
- className="card card-compact"
+ className={`card card-compact${isLoading ? ' card-loading' : ''}`}
aria-label={`View details for ${decodedName}`}
>
@@ -132,17 +142,23 @@ const ServiceCard = React.memo(function ServiceCard({ service, isOpen, onToggle
)}
- {openingStatus.isOpen && (
-
- Open Now
-
- )}
-
- {/* Appointment Only indicator */}
- {openingStatus.isAppointmentOnly && (
-
- Appointment Only
+ {is24Hour ? (
+
+ Open 24/7
+ ) : (
+ <>
+ {openingStatus.isOpen && (
+
+ Open Now
+
+ )}
+ {openingStatus.isAppointmentOnly && (
+
+ Appointment Only
+
+ )}
+ >
)}
@@ -202,7 +218,7 @@ const ServiceCard = React.memo(function ServiceCard({ service, isOpen, onToggle
)}
- {service.openTimes && service.openTimes.length > 0 && !service.isOpen247 ? (
+ {is24Hour ? null : service.openTimes && service.openTimes.length > 0 ? (