cherry picking
This commit is contained in:
63
latosa-frontend/app/history/[slug]/page.tsx
Normal file
63
latosa-frontend/app/history/[slug]/page.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
export default async function HistoryDetails({
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
params: Promise<{ slug: string }>;
|
||||||
|
}) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const default_img: string = "https://shadcnblocks.com/images/block/placeholder-dark-1.svg"
|
||||||
|
const default_style: string = "blog-paragraph mb-5 text-muted-foreground md:text-base lg:max-w-2xl lg:text-lg"
|
||||||
|
const sub_header_style: string = "py-12 mb-3 text-pretty text-xl font-semibold md:mb-4 md:text-4xl lg:mb-6 lg:max-w-3xl lg:text-3xl"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex flex-col w-full lg:md:py-24 sm:py-24">
|
||||||
|
<section className="container self-center max-w-2xl">
|
||||||
|
<div className="blog-title w-full h-28 justify-center">
|
||||||
|
<h1 className="mb-3 text-pretty text-3xl font-semibold lg:text-5xl">
|
||||||
|
{slug}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div className="content">
|
||||||
|
<div>
|
||||||
|
<h2 className={sub_header_style}>Subtitle 1</h2>
|
||||||
|
<p className={default_style}>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti architecto incidunt, hic in consectetur eligendi nobis numquam tenetur sit repellat et unde, maxime ducimus autem esse temporibus omnis eum molestias!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src={default_img}
|
||||||
|
alt={slug}
|
||||||
|
className="aspect-[16/9] mb-5 rounded-sm h-full w-full object-cover object-center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 className={sub_header_style}>Subtitle 2</h2>
|
||||||
|
<p className={default_style}>
|
||||||
|
Lorem ipsm dolor sit amet, consectetur adipisicing elit. Deleniti architecto incidunt, hic in consectetur eligendi nobis numquam tenetur sit repellat et unde, maxime ducimus autem esse temporibus omnis eum molestias!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src={default_img}
|
||||||
|
alt={slug}
|
||||||
|
className="aspect-[16/9] mb-5 rounded-sm h-full w-full object-cover object-center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 className={sub_header_style}>Subtitle 3</h2>
|
||||||
|
<p className={default_style}>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti architecto incidunt, hic in consectetur eligendi nobis numquam tenetur sit repellat et unde, maxime ducimus autem esse temporibus omnis eum molestias!
|
||||||
|
</p>
|
||||||
|
<p className={default_style}>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti architecto incidunt, hic in consectetur eligendi nobis numquam tenetur sit repellat et unde, maxime ducimus autem esse temporibus omnis eum molestias!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
9
latosa-frontend/app/history/page.tsx
Normal file
9
latosa-frontend/app/history/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import Blog from "@/components/blog";
|
||||||
|
|
||||||
|
export default function History() {
|
||||||
|
return(
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Blog />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
93
latosa-frontend/components/blog.tsx
Normal file
93
latosa-frontend/components/blog.tsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { ArrowRight } from "lucide-react";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
const posts = [
|
||||||
|
{
|
||||||
|
id: "post-1",
|
||||||
|
title: "Duis sem sem, gravida vel porttitor eu, volutpat ut arcu",
|
||||||
|
summary:
|
||||||
|
"Pellentesque eget quam ligula. Sed felis ante, consequat nec ultrices ut, ornare quis metus. Vivamus sit amet tortor vel enim sollicitudin hendrerit.",
|
||||||
|
label: "Ut varius dolor turpis",
|
||||||
|
author: "Jane Doe",
|
||||||
|
published: "1 Jan 2024",
|
||||||
|
href: "#",
|
||||||
|
image: "https://shadcnblocks.com/images/block/placeholder-dark-1.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "post-2",
|
||||||
|
title: "Duis sem sem, gravida vel porttitor eu, volutpat ut arcu",
|
||||||
|
summary:
|
||||||
|
"Pellentesque eget quam ligula. Sed felis ante, consequat nec ultrices ut, ornare quis metus. Vivamus sit amet tortor vel enim sollicitudin hendrerit.",
|
||||||
|
label: "Ut varius dolor turpis",
|
||||||
|
author: "Jane Doe",
|
||||||
|
published: "1 Jan 2024",
|
||||||
|
href: "#",
|
||||||
|
image: "https://shadcnblocks.com/images/block/placeholder-dark-1.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "post-3",
|
||||||
|
title: "Duis sem sem, gravida vel porttitor eu, volutpat ut arcu",
|
||||||
|
summary:
|
||||||
|
"Pellentesque eget quam ligula. Sed felis ante, consequat nec ultrices ut, ornare quis metus. Vivamus sit amet tortor vel enim sollicitudin hendrerit.",
|
||||||
|
label: "Ut varius dolor turpis",
|
||||||
|
author: "Jane Doe",
|
||||||
|
published: "1 Jan 2024",
|
||||||
|
href: "#",
|
||||||
|
image: "https://shadcnblocks.com/images/block/placeholder-dark-1.svg",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const Blog = () => {
|
||||||
|
return (
|
||||||
|
<section className="self-center lg:md:py-24 sm:py-12">
|
||||||
|
<div className="container flex flex-col items-center gap-16 lg:px-16">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="mb-3 text-pretty text-3xl font-semibold md:mb-4 md:text-4xl lg:mb-6 lg:max-w-3xl lg:text-5xl">
|
||||||
|
En savoir plus sur ce sport
|
||||||
|
</h2>
|
||||||
|
<p className="mb-8 text-muted-foreground md:text-base lg:max-w-2xl lg:text-lg">
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Elig
|
||||||
|
doloremque mollitia fugiat omnis! Porro facilis quo animi
|
||||||
|
consequatur. Explicabo.
|
||||||
|
</p>
|
||||||
|
<Button variant="link" className="w-full sm:w-auto">
|
||||||
|
Explore all posts
|
||||||
|
<ArrowRight className="ml-2 size-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3 lg:gap-8">
|
||||||
|
{posts.map((post) => (
|
||||||
|
<a
|
||||||
|
key={post.id}
|
||||||
|
href={post.href}
|
||||||
|
className="flex flex-col overflow-clip rounded-xl border border-border"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src={post.image}
|
||||||
|
alt={post.title}
|
||||||
|
className="aspect-[16/9] h-full w-full object-cover object-center"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="px-6 py-8 md:px-8 md:py-10 lg:px-10 lg:py-12">
|
||||||
|
<h3 className="mb-3 text-lg font-semibold md:mb-4 md:text-xl lg:mb-6">
|
||||||
|
{post.title}
|
||||||
|
</h3>
|
||||||
|
<p className="mb-3 text-muted-foreground md:mb-4 lg:mb-6">
|
||||||
|
{post.summary}
|
||||||
|
</p>
|
||||||
|
<p className="flex items-center hover:underline">
|
||||||
|
Read more
|
||||||
|
<ArrowRight className="ml-2 size-4" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Blog;
|
||||||
112
latosa-frontend/components/testimonial.tsx
Normal file
112
latosa-frontend/components/testimonial.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Star } from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Carousel,
|
||||||
|
CarouselApi,
|
||||||
|
CarouselContent,
|
||||||
|
CarouselItem,
|
||||||
|
} from "@/components/ui/carousel";
|
||||||
|
|
||||||
|
const testimonials = [
|
||||||
|
{
|
||||||
|
id: "testimonial-1",
|
||||||
|
text: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Elig doloremque mollitia fugiat omnis! Porro facilis quo animi consequatur. Explicabo.",
|
||||||
|
name: "Customer Name",
|
||||||
|
role: "Position at Company",
|
||||||
|
avatar: "https://shadcnblocks.com/images/block/avatar-1.webp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "testimonial-2",
|
||||||
|
text: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Elig doloremque mollitia fugiat omnis! Porro facilis quo animi consequatur. Explicabo.",
|
||||||
|
name: "Customer Name",
|
||||||
|
role: "Position at Company",
|
||||||
|
avatar: "https://shadcnblocks.com/images/block/avatar-2.webp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "testimonial-3",
|
||||||
|
text: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Elig doloremque mollitia fugiat omnis! Porro facilis quo animi consequatur. Explicabo.",
|
||||||
|
name: "Customer Name",
|
||||||
|
role: "Position at Company",
|
||||||
|
avatar: "https://shadcnblocks.com/images/block/avatar-3.webp",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const Testimonial = () => {
|
||||||
|
const [api, setApi] = useState<CarouselApi>();
|
||||||
|
const [current, setCurrent] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!api) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateCurrent = () => {
|
||||||
|
setCurrent(api.selectedScrollSnap());
|
||||||
|
};
|
||||||
|
|
||||||
|
api.on("select", updateCurrent);
|
||||||
|
return () => {
|
||||||
|
api.off("select", updateCurrent);
|
||||||
|
};
|
||||||
|
}, [api]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="lg:md:py-24 sm:py-12">
|
||||||
|
<Carousel setApi={setApi}>
|
||||||
|
<CarouselContent>
|
||||||
|
{testimonials.map((testimonial) => (
|
||||||
|
<CarouselItem key={testimonial.id}>
|
||||||
|
<div className="flex flex-col items-center text-center">
|
||||||
|
<p className="mb-8 max-w-4xl font-medium md:px-8 lg:text-3xl">
|
||||||
|
“{testimonial.text}”
|
||||||
|
</p>
|
||||||
|
<Avatar className="mb-2 size-12 md:size-24">
|
||||||
|
<AvatarImage src={testimonial.avatar} />
|
||||||
|
<AvatarFallback>
|
||||||
|
{testimonial.name}
|
||||||
|
</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
<p className="mb-1 text-sm font-medium md:text-lg">
|
||||||
|
{testimonial.name}
|
||||||
|
</p>
|
||||||
|
<p className="mb-2 text-sm text-muted-foreground md:text-lg">
|
||||||
|
{testimonial.role}
|
||||||
|
</p>
|
||||||
|
<div className="mt-2 flex items-center gap-0.5">
|
||||||
|
<Star className="size-5 fill-primary stroke-none" />
|
||||||
|
<Star className="size-5 fill-primary stroke-none" />
|
||||||
|
<Star className="size-5 fill-primary stroke-none" />
|
||||||
|
<Star className="size-5 fill-primary stroke-none" />
|
||||||
|
<Star className="size-5 fill-primary stroke-none" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CarouselItem>
|
||||||
|
))}
|
||||||
|
</CarouselContent>
|
||||||
|
</Carousel>
|
||||||
|
<div className="flex justify-center py-16">
|
||||||
|
{testimonials.map((testimonial, index) => (
|
||||||
|
<Button
|
||||||
|
key={testimonial.id}
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
api?.scrollTo(index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`size-2.5 rounded-full ${index === current ? "bg-primary" : "bg-input"}`}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Testimonial;
|
||||||
Reference in New Issue
Block a user