Files
portfolio/src/components/ProjectCard.astro

240 lines
6.6 KiB
Plaintext

---
import { getAllProjectImages } from "@lib/utils";
import Paragraph from "@components/Paragraph.astro";
import TextLink from "@components/TextLink.astro";
import Token from "@components/Token.astro";
import { Icon } from "astro-icon/components";
import { Image } from "astro:assets";
import type { CollectionEntry } from "astro:content";
import { slugify } from "@lib/utils";
interface Props {
project: CollectionEntry<"projects">;
textOn?: "left" | "right";
quality?: number;
class?: string;
}
const {
project,
textOn = "left",
quality = "80",
class: className,
...attrs
} = Astro.props;
const images = getAllProjectImages(project);
const translateXOptions = [
"group-hover:translate-x-8",
"group-hover:translate-x-9",
"group-hover:translate-x-10",
"group-hover:translate-x-11",
"group-hover:translate-x-12",
"group-hover:translate-x-13",
"group-hover:translate-x-14",
"group-hover:translate-x-15",
"group-hover:translate-x-16",
"group-hover:translate-x-17",
"group-hover:translate-x-18",
"group-hover:translate-x-19",
"group-hover:translate-x-20",
"group-hover:translate-x-21",
"group-hover:translate-x-22",
"group-hover:translate-x-23",
"group-hover:translate-x-24",
"group-hover:-translate-x-8",
"group-hover:-translate-x-9",
"group-hover:-translate-x-10",
"group-hover:-translate-x-11",
"group-hover:-translate-x-12",
"group-hover:-translate-x-13",
"group-hover:-translate-x-14",
"group-hover:-translate-x-15",
"group-hover:-translate-x-16",
"group-hover:-translate-x-17",
"group-hover:-translate-x-18",
"group-hover:-translate-x-19",
"group-hover:-translate-x-20",
"group-hover:-translate-x-21",
"group-hover:-translate-x-22",
"group-hover:-translate-x-23",
"group-hover:-translate-x-24"
];
const translateYOptions = [
"group-hover:translate-y-8",
"group-hover:translate-y-9",
"group-hover:translate-y-10",
"group-hover:translate-y-11",
"group-hover:translate-y-12",
"group-hover:translate-y-13",
"group-hover:translate-y-14",
"group-hover:translate-y-15",
"group-hover:translate-y-16",
"group-hover:translate-y-17",
"group-hover:translate-y-18",
"group-hover:translate-y-19",
"group-hover:translate-y-20",
"group-hover:translate-y-21",
"group-hover:translate-y-22",
"group-hover:translate-y-23",
"group-hover:translate-y-24",
"group-hover:-translate-y-9",
"group-hover:-translate-y-10",
"group-hover:-translate-y-11",
"group-hover:-translate-y-12",
"group-hover:-translate-y-13",
"group-hover:-translate-y-14",
"group-hover:-translate-y-15",
"group-hover:-translate-y-16",
"group-hover:-translate-y-17",
"group-hover:-translate-y-18",
"group-hover:-translate-y-19",
"group-hover:-translate-y-20",
"group-hover:-translate-y-21",
"group-hover:-translate-y-22",
"group-hover:-translate-y-23",
"group-hover:-translate-y-24"
];
const rotateOptions = [
"rotate-1",
"rotate-2",
"rotate-3",
"rotate-4",
"rotate-5",
"rotate-6",
"rotate-7",
"rotate-8",
"rotate-9",
"rotate-10",
"rotate-11",
"rotate-12",
"-rotate-1",
"-rotate-2",
"-rotate-3",
"-rotate-4",
"-rotate-5",
"-rotate-6",
"-rotate-7",
"-rotate-8",
"-rotate-9",
"-rotate-10",
"-rotate-11",
"-rotate-12"
];
const projectHasBody = project.body && project.body.trim().length > 0;
const link = `/projects/${slugify(project.data.type)}/${slugify(project.data.slug)}/`;
---
<div
class:list={["grid grid-cols-1 text-left md:grid-cols-2", className]}
{...attrs}
>
<div
class:list={[
"order-1 flex flex-col items-start justify-center py-4",
textOn === "right" ? "md:order-2" : "md:order-1"
]}
>
<span
><h2 class="font-header-alt inline-block text-lg font-semibold">
{
projectHasBody && (
<TextLink href={link}>{project.data.title}</TextLink>
)
}{!projectHasBody && project.data.title}{
!project.data.ongoing && (
<span class="text-sm font-light italic">
{" "}
({project.data.date.getFullYear()})
</span>
)
}
</h2></span
>
<h3 class="font-header-alt font-base font-medium">
{project.data.role}
</h3>
<div class="mt-2">
<Token>{project.data.type}</Token>
</div>
{
project.data.keyFigure && project.data.keyFigure.length > 0 && (
<div class="mt-2 text-sm">
{project.data.keyFigure.map((figure) => {
return (
<div>
<span class="font-bold">{figure.title}:</span>
<span>
{figure.href && (
<TextLink href={figure.href}>{figure.name}</TextLink>
)}
{!figure.href && figure.name}
</span>
</div>
);
})}
</div>
)
}
<Paragraph
class:list={["px-0", "my-2", textOn === "right" ? "" : "md:pr-10"]}
>{project.data.description}</Paragraph
>
{
project.data.externalLinks !== undefined && (
<span class="relative order-3 ml-auto flex w-full items-start justify-start space-x-2 text-xl">
{project.data.externalLinks.map((link) => (
<TextLink
href={link.href}
includeExternalLinkIcon={false}
aria-label={link.name}
>
<Icon name={link.icon} />
</TextLink>
))}
</span>
)
}
</div>
<div
class:list={[
"group relative order-2 ml-auto flex h-full min-h-64 w-full items-center justify-center",
textOn === "right" ? "md:order-1" : "md:order-2"
]}
>
{
images
.reverse()
.map((image, index) => (
<Image
id={`hero-image-${index}`}
class:list={[
"animate-floaty absolute h-48 w-auto origin-center transform rounded object-cover shadow-lg/50 transition duration-300 ease-in-out md:group-hover:z-30 md:group-hover:scale-130 md:hover:z-40",
translateXOptions[
Math.floor(Math.random() * translateXOptions.length)
],
translateYOptions[
Math.floor(Math.random() * translateYOptions.length)
],
rotateOptions[Math.floor(Math.random() * rotateOptions.length)]
]}
src={image}
alt=""
loading="lazy"
layout="constrained"
fit="cover"
height={250}
style={`animation-delay: -${Math.floor(Math.random() * (12 - 4) + 4)}s; animation-direction: ${Math.random() < 0.5 ? "normal" : "reverse"};`}
quality={quality}
/>
))
}
</div>
</div>