Skip to content

Commit 11268a0

Browse files
committed
fix(ci): resolve TypeScript and formatting issues post-i18n
- Update projects/[slug]/page.tsx to use getTranslations() server-side instead of importing PROJECTS constant - Fix test type error for project.links.demo by adding proper type assertion - Format Skills.tsx (lines 43, 63) to comply with Prettier rules - Format changelog and test files All CI checks now pass: - Prettier format check: passed - ESLint: no warnings or errors - TypeScript: no type errors - Tests: 156 tests passed (15 test files)
1 parent 06728be commit 11268a0

4 files changed

Lines changed: 54 additions & 43 deletions

File tree

app/[locale]/projects/[slug]/page.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
import Link from 'next/link';
22
import { notFound } from 'next/navigation';
3+
import { getTranslations } from 'next-intl/server';
34

4-
import { Project } from '@/core/entities/Project';
5-
import { PROJECTS } from '@/shared/constants/projects';
5+
import { Project, type ProjectData } from '@/core/entities/Project';
66

77
interface ProjectDetailPageProps {
8-
params: Promise<{ slug: string }>;
8+
params: Promise<{ slug: string; locale: string }>;
99
}
1010

1111
export async function generateStaticParams() {
12-
return PROJECTS.map((project) => ({
12+
const t = await getTranslations('projects');
13+
const projectsData = t.raw('items') as ProjectData[];
14+
15+
return projectsData.map((project) => ({
1316
slug: project.detailSlug ?? project.id,
1417
}));
1518
}
1619

1720
export default async function ProjectDetailPage({ params }: ProjectDetailPageProps) {
1821
const { slug } = await params;
19-
const projectData = PROJECTS.find((project) => (project.detailSlug ?? project.id) === slug);
22+
const t = await getTranslations('projects');
23+
const projectsData = t.raw('items') as ProjectData[];
24+
25+
const projectData = projectsData.find((project) => (project.detailSlug ?? project.id) === slug);
2026

2127
if (!projectData) {
2228
notFound();
Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,31 @@
1-
# Changelog · 10/11/2025 · 23:13
2-
3-
## Resumen
4-
5-
- Nueva visualización de habilidades con gráfico donut y leyenda dinámica para comunicar el stack de un vistazo.
6-
- Localización completa de la navegación y el footer, incluyendo selector de idioma accesible y enlaces sociales traducidos.
7-
- Refactor de tests asociados para cubrir la nueva UI y las cadenas i18n.
8-
9-
## Detalles
10-
11-
### feat(skills): visualización híbrida con donut (#17)
12-
13-
- Sustituye el sumario plano por un gráfico `conic-gradient` animado y leyenda multicolor ligada a `mainLanguagesShare`.
14-
- Mantiene las tarjetas de categorías, ahora con etiquetas y progresos dependientes de `next-intl`.
15-
- Añade textos de soporte (`visualization.title`, `visualization.legendLabel`, etc.) en `messages/es.json` y `messages/en.json`.
16-
17-
### feat(layout): selector de idioma e i18n en navegación/footer (#28)
18-
19-
- Refactoriza `Navigation` para consumir `next-intl`, ofrecer selector de idioma (desktop y mobile) y preservar el hash actual al cambiar de locale.
20-
- Centraliza la configuración en `NAV_SECTIONS` y `SOCIAL_LINK_URLS` y expone las etiquetas a través de las traducciones.
21-
- Actualiza `Footer` para leer el branding, tagline y accesibilidad de enlaces desde i18n.
22-
23-
### test: cobertura para UI localizada
24-
25-
- Envuelve pruebas de `Navigation`, `Footer` y `Skills` con `NextIntlClientProvider` y añade assertions específicas del nuevo gráfico y switcher.
26-
- Ejecución de `npm run lint` y `npm run test` sin incidencias tras los cambios.
27-
28-
## Notas
29-
30-
- Evaluar una librería ligera de charts si se requiere interactividad adicional (tooltips o filtros) en futuras iteraciones.
31-
- Actualizar los enlaces reales de GitHub/LinkedIn cuando se disponga de las URLs definitivas en producción.
32-
1+
# Changelog · 10/11/2025 · 23:13
2+
3+
## Resumen
4+
5+
- Nueva visualización de habilidades con gráfico donut y leyenda dinámica para comunicar el stack de un vistazo.
6+
- Localización completa de la navegación y el footer, incluyendo selector de idioma accesible y enlaces sociales traducidos.
7+
- Refactor de tests asociados para cubrir la nueva UI y las cadenas i18n.
8+
9+
## Detalles
10+
11+
### feat(skills): visualización híbrida con donut (#17)
12+
13+
- Sustituye el sumario plano por un gráfico `conic-gradient` animado y leyenda multicolor ligada a `mainLanguagesShare`.
14+
- Mantiene las tarjetas de categorías, ahora con etiquetas y progresos dependientes de `next-intl`.
15+
- Añade textos de soporte (`visualization.title`, `visualization.legendLabel`, etc.) en `messages/es.json` y `messages/en.json`.
16+
17+
### feat(layout): selector de idioma e i18n en navegación/footer (#28)
18+
19+
- Refactoriza `Navigation` para consumir `next-intl`, ofrecer selector de idioma (desktop y mobile) y preservar el hash actual al cambiar de locale.
20+
- Centraliza la configuración en `NAV_SECTIONS` y `SOCIAL_LINK_URLS` y expone las etiquetas a través de las traducciones.
21+
- Actualiza `Footer` para leer el branding, tagline y accesibilidad de enlaces desde i18n.
22+
23+
### test: cobertura para UI localizada
24+
25+
- Envuelve pruebas de `Navigation`, `Footer` y `Skills` con `NextIntlClientProvider` y añade assertions específicas del nuevo gráfico y switcher.
26+
- Ejecución de `npm run lint` y `npm run test` sin incidencias tras los cambios.
27+
28+
## Notas
29+
30+
- Evaluar una librería ligera de charts si se requiere interactividad adicional (tooltips o filtros) en futuras iteraciones.
31+
- Actualizar los enlaces reales de GitHub/LinkedIn cuando se disponga de las URLs definitivas en producción.

src/features/skills/Skills.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ export function Skills() {
4040
let cumulative = 0;
4141
const segments = languages.map((language, index) => {
4242
const rawNormalized =
43-
totalUsage > 0 ? (language.usagePercentage / totalUsage) * 100 : languages.length > 0 ? 100 / languages.length : 0;
43+
totalUsage > 0
44+
? (language.usagePercentage / totalUsage) * 100
45+
: languages.length > 0
46+
? 100 / languages.length
47+
: 0;
4448
const normalized = Number(rawNormalized.toFixed(2));
4549
const start = cumulative;
4650
cumulative += normalized;
@@ -60,7 +64,9 @@ export function Skills() {
6064
.map((segment) => `${segment.color} ${segment.start}% ${segment.end}%`)
6165
.join(', ');
6266
const donutBackground =
63-
segments.length > 0 ? `conic-gradient(${gradientStops})` : 'conic-gradient(#38bdf8 0deg, #38bdf8 360deg)';
67+
segments.length > 0
68+
? `conic-gradient(${gradientStops})`
69+
: 'conic-gradient(#38bdf8 0deg, #38bdf8 360deg)';
6470

6571
const contributionsValue = tSkills('stats.contributions.value', {
6672
count: summary.contributionsLastYear.toLocaleString(numberLocale),

tests/features/projects/Projects.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { NextIntlClientProvider } from 'next-intl';
44

55
import esMessages from '../../../messages/es.json';
66
import { Projects } from '@/features/projects/Projects';
7+
import type { ProjectData } from '@/core/entities/Project';
78

89
function renderProjects() {
910
return render(
@@ -41,9 +42,7 @@ describe('Projects Section', () => {
4142

4243
it('should display project descriptions', () => {
4344
renderProjects();
44-
expect(
45-
screen.getByText(esMessages.projects.items[0].description)
46-
).toBeInTheDocument();
45+
expect(screen.getByText(esMessages.projects.items[0].description)).toBeInTheDocument();
4746
});
4847

4948
it('should display tech stack for each project', () => {
@@ -65,7 +64,8 @@ describe('Projects Section', () => {
6564
it('should render demo links when available', () => {
6665
renderProjects();
6766
const demoLinks = screen.queryAllByRole('link', { name: /demo/i });
68-
const hasDemo = esMessages.projects.items.some((project) => Boolean(project.links.demo));
67+
const projectsData = esMessages.projects.items as unknown as ProjectData[];
68+
const hasDemo = projectsData.some((project) => Boolean(project.links.demo));
6969

7070
if (hasDemo) {
7171
expect(demoLinks.length).toBeGreaterThan(0);

0 commit comments

Comments
 (0)