Skip to content

Commit af05b63

Browse files
committed
Improvements: The isVerified mark is now dynamic: made possible through the upload of certificates
1 parent 84e782f commit af05b63

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

src/frontend/src/components/client/ServiceListItem.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const ServiceListItem: React.FC<ServiceListItemProps> = React.memo(
2222
({ service, isGridItem = false, retainMobileLayout = false }) => {
2323
// Fetch the latest service data to get isVerified
2424
const { service: fetchedService } = useServiceById(service.id);
25-
const isVerified = fetchedService?.isVerified === true;
25+
const isVerified = fetchedService?.isVerified;
2626
// Use the same logic as ServiceDetailPageComponent for review count
2727
const { reviews = [], getAverageRating } = useServiceReviews(service.id);
2828
const visibleReviews = Array.isArray(reviews)
@@ -44,6 +44,8 @@ const ServiceListItem: React.FC<ServiceListItemProps> = React.memo(
4444
loading: false,
4545
};
4646

47+
console.log("From Service List Item", fetchedService);
48+
4749
// Define layout classes based on props
4850
const itemWidthClass = isGridItem
4951
? "w-full" // Full width for grid items
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import React from "react";
2+
import ServiceListItem from "./ServiceListItem"; // Your individual card component
3+
import {
4+
EnrichedService,
5+
useAllServicesWithProviders,
6+
} from "../../hooks/serviceInformation";
7+
import { getCategoryImage } from "../../utils/serviceHelpers";
8+
9+
interface ServicesListProps {
10+
className?: string;
11+
}
12+
13+
const ServicesList: React.FC<ServicesListProps> = ({ className = "" }) => {
14+
const { services, loading, error } = useAllServicesWithProviders();
15+
16+
const enhanceService = (service: EnrichedService): EnrichedService => ({
17+
...service,
18+
heroImage: getCategoryImage(service.category.name),
19+
providerName: service.providerName,
20+
providerAvatar: service.providerAvatar,
21+
rating: {
22+
average: service.rating.average ?? 0,
23+
count: service.rating.count ?? 0,
24+
},
25+
price: {
26+
amount: service.price.amount,
27+
unit: service.price.unit,
28+
display: `₱${service.price.amount.toLocaleString(undefined, {
29+
minimumFractionDigits: 2,
30+
maximumFractionDigits: 2,
31+
})}`,
32+
},
33+
location: {
34+
serviceRadius: service.location?.serviceRadius,
35+
address: service.location?.address,
36+
city: service.location?.city,
37+
state: service.location?.state,
38+
serviceRadiusUnit: service.location?.serviceRadiusUnit,
39+
},
40+
});
41+
42+
if (loading) {
43+
return (
44+
<div className={`${className}`}>
45+
<div className="mb-4 flex items-center justify-between">
46+
<div className="h-7 w-32 animate-pulse rounded-md bg-gray-200"></div>
47+
</div>
48+
<div className="grid grid-cols-1 gap-4 lg:grid-cols-4">
49+
{[...Array(4)].map((_, i) => (
50+
<div
51+
key={i}
52+
className="overflow-hidden rounded-lg bg-white shadow-sm"
53+
>
54+
{/* Image skeleton */}
55+
<div className="aspect-video w-full animate-pulse bg-gray-200"></div>
56+
{/* Content skeleton */}
57+
<div className="p-3">
58+
<div className="mb-2 flex items-center justify-between">
59+
<div className="h-4 w-20 animate-pulse rounded bg-gray-200"></div>
60+
<div className="h-3 w-16 animate-pulse rounded bg-gray-200"></div>
61+
</div>
62+
<div className="mb-2 h-4 w-full animate-pulse rounded bg-gray-200"></div>
63+
<div className="mb-2 h-3 w-24 animate-pulse rounded bg-gray-200"></div>
64+
<div className="flex items-center justify-between border-t border-gray-100 pt-2">
65+
<div className="h-5 w-16 animate-pulse rounded bg-gray-200"></div>
66+
<div className="h-3 w-12 animate-pulse rounded bg-gray-200"></div>
67+
</div>
68+
</div>
69+
</div>
70+
))}
71+
</div>
72+
</div>
73+
);
74+
}
75+
76+
if (error) {
77+
return (
78+
<div className={`p-4 ${className}`}>
79+
<h2 className="mb-4 text-lg font-bold sm:text-xl">Book Now!</h2>
80+
<p className="text-red-500">Error loading services: {error.message}</p>
81+
</div>
82+
);
83+
}
84+
85+
return (
86+
<div className={`w-full max-w-full ${className}`}>
87+
<div className="mb-4 flex items-center justify-between">
88+
<h2 className="text-lg font-bold sm:text-xl">Book Now!</h2>
89+
</div>
90+
91+
{services.length === 0 ? (
92+
<div className="py-12 text-center">
93+
<p className="text-gray-500">
94+
No top-rated services available at the moment.
95+
</p>
96+
</div>
97+
) : (
98+
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-4">
99+
{services.map((service) => (
100+
<div key={service.id}>
101+
<ServiceListItem service={enhanceService(service)} />
102+
</div>
103+
))}
104+
</div>
105+
)}
106+
</div>
107+
);
108+
};
109+
110+
export default ServicesList;

src/frontend/src/hooks/serviceDetail.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ const formatServiceForDetailPage = (
134134
},
135135
media: service.imageUrls, // Default empty media array
136136
requirements: [], // Default empty requirements
137-
isVerified: true, // Default value
137+
isVerified: service.isVerifiedService, // Default value
138138
slug: service.id, // Using ID as slug
139139
heroImage:
140140
service.category.imageUrl || getCategoryImage(service.category.name),

src/frontend/src/pages/client/home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
22
import { useUserProfile } from "../../hooks/useUserProfile";
33
import Header from "../../components/client/Header";
44
import Categories from "../../components/client/Categories";
5-
import ServiceList from "../../components/client/ServiceListReact";
5+
import ServiceList from "../../components/client/ServiceListRow";
66
import BottomNavigation from "../../components/client/BottomNavigation";
77
import { useServiceManagement } from "../../hooks/serviceManagement";
88
import { useBookingManagement } from "../../hooks/bookingManagement";

0 commit comments

Comments
 (0)