Files
portifolio-evandrodevbr/app/components/story/notebookProjects.ts
T
Evandro Fonseca Junior 8b12e51bc5
CI / verify (push) Failing after 5m9s
feat: refine portfolio showcase, services and quality lab
Align the notebook browser with the physical LCD, refresh real project captures and navigation, simplify service content, and stabilize hero hydration.
2026-09-05 14:20:54 -03:00

69 lines
1.8 KiB
TypeScript

import type { PortfolioProjectView } from "@/lib/portfolio-data";
export type NotebookProject = {
id: string;
title: string;
subtitle: string;
demoUrl: PortfolioProjectView["demoUrl"];
demoAvailability: PortfolioProjectView["demoAvailability"];
demoCheckedAt: PortfolioProjectView["demoCheckedAt"];
technologies: string[];
screenshotSrc: string;
screenshotWidth: number;
screenshotHeight: number;
};
const NOTEBOOK_ORDER = [
"nutriscan",
"sc-plus",
"sev-modaintima",
"as-servicos",
] as const;
const SCREENSHOT_BY_PROJECT_ID: Record<
(typeof NOTEBOOK_ORDER)[number],
string
> = {
nutriscan: "/assets/notebook/nutriscan.webp",
"sc-plus": "/assets/notebook/sc-plus.webp",
"sev-modaintima": "/assets/notebook/sev-modaintima.webp",
"as-servicos": "/assets/notebook/as-servicos.webp",
};
function isApprovedDemoUrl(
value: PortfolioProjectView["demoUrl"],
): value is string {
return typeof value === "string" && /^https?:\/\//.test(value);
}
export function selectNotebookProjects(
projects: readonly PortfolioProjectView[],
): NotebookProject[] {
return NOTEBOOK_ORDER.flatMap((id) => {
const project = projects.find((candidate) => candidate.id === id);
const screenshotSrc = SCREENSHOT_BY_PROJECT_ID[id];
if (
!project ||
(project.demoUrl !== null && !isApprovedDemoUrl(project.demoUrl))
) {
return [];
}
return [
{
id: project.id,
title: project.title,
subtitle: project.subtitle,
demoUrl: project.demoUrl,
demoAvailability: project.demoAvailability,
demoCheckedAt: project.demoCheckedAt,
technologies: [...project.technologies],
screenshotSrc,
screenshotWidth: 1600,
screenshotHeight: 1000,
},
];
});
}