Files
yingfungsolar/src/components/site/Cases.tsx
T
2026-09-11 15:49:41 +08:00

98 lines
3.8 KiB
TypeScript

import { Box, Grid, Heading, HStack, Image, Stack, Text } from "@chakra-ui/react";
import { MapPin } from "lucide-react";
import type { CaseStudy } from "../../db/schema";
import { Section } from "./Section";
import { SectionHeading } from "./SectionHeading";
export function Cases({ items }: { items: CaseStudy[] }) {
if (items.length === 0) return null;
const [featured, ...rest] = items;
return (
<Section id="cases" tone="white">
<SectionHeading
eyebrow="完成案例"
title="真實村屋工程案例"
description="我哋為香港各區村屋提供專業太陽能方案,累積豐富施工經驗。"
/>
<Stack gap={{ base: 12, md: 16 }}>
{/* 首案例 featured:雜誌式大圖排版 */}
<Grid
templateColumns={{ base: "1fr", lg: "1.2fr 0.8fr" }}
gap={{ base: 5, lg: 10 }}
alignItems="end"
role="group"
>
<Box overflow="hidden">
<Image
src={featured.imageUrl ?? undefined}
alt={featured.title}
w="full"
aspectRatio={{ base: "4 / 3", lg: "16 / 10" }}
objectFit="cover"
transition="transform .5s"
_groupHover={{ transform: "scale(1.03)" }}
/>
</Box>
<Stack gap="3">
<HStack gap="3" fontSize="xs" letterSpacing="0.1em" color="fg.muted" fontWeight="medium">
<Text>{featured.completedAt}</Text>
{featured.location && (
<HStack gap="1" color="brand.700">
<MapPin size={12} />
<Text>{featured.location}</Text>
</HStack>
)}
</HStack>
<Heading as="h3" fontSize={{ base: "xl", md: "2xl" }} fontWeight="700" color="ink" lineHeight="1.35" _groupHover={{ color: "brand.700" }} transition="color .2s">
{featured.title}
</Heading>
{featured.description && (
<Text fontSize="sm" color="fg.muted" lineHeight="1.9">
{featured.description}
</Text>
)}
</Stack>
</Grid>
{rest.length > 0 && (
<Grid templateColumns={{ base: "1fr", md: "repeat(2, 1fr)", lg: `repeat(${Math.min(rest.length, 3)}, 1fr)` }} gap={{ base: 10, md: 8 }}>
{rest.map((item) => (
<Stack key={item.id} gap="3" role="group" borderTopWidth="2px" borderColor="ink" pt="5">
<Box overflow="hidden">
<Image
src={item.imageUrl ?? undefined}
alt={item.title}
w="full"
aspectRatio="4 / 3"
objectFit="cover"
transition="transform .5s"
_groupHover={{ transform: "scale(1.03)" }}
/>
</Box>
<HStack gap="3" fontSize="xs" letterSpacing="0.1em" color="fg.muted" fontWeight="medium">
<Text>{item.completedAt}</Text>
{item.location && (
<HStack gap="1" color="brand.700">
<MapPin size={12} />
<Text>{item.location}</Text>
</HStack>
)}
</HStack>
<Heading as="h3" fontSize="lg" fontWeight="700" color="ink" lineHeight="1.4" _groupHover={{ color: "brand.700" }} transition="color .2s">
{item.title}
</Heading>
{item.description && (
<Text fontSize="sm" color="fg.muted" lineHeight="1.8">
{item.description}
</Text>
)}
</Stack>
))}
</Grid>
)}
</Stack>
</Section>
);
}