Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions front/src/app/embalse-cuenca/[cuenca]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { EmbalsesCuencaPod, getEmbalsesPorCuenca } from "@/pods/embalse-cuenca";
import { cuencas } from "@/core/constants/cuencas.constants";
import { Metadata } from "next";
import { mapListaCuencasDesdeApiParaVista } from "@/pods/embalse-cuenca-list/embalse-cuenca.mapper";
import { notFound } from "next/navigation";

interface Props {
params: Promise<{ cuenca: string }>;
}

const getCuencaBySlug = (slug: string) => {
return Object.values(cuencas).find((cuenca) => cuenca.slug === slug);
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { cuenca } = await params;
const datosCuenca = getCuencaBySlug(cuenca.toString());

if (!datosCuenca) {
return {};
}

return {
title: `Embalses de ${datosCuenca.nombre}`,
};
}

export default async function EmbalseCuencaListadoPage({
params,
}: Props): Promise<React.JSX.Element> {
const { cuenca } = await params;
const datosCuenca = getCuencaBySlug(cuenca.toString());
if (!datosCuenca) {
notFound();
}
const embalsesPorCuencaDesdeApi = await getEmbalsesPorCuenca(
datosCuenca.nombre,
);
const embalsesPorCuenca = mapListaCuencasDesdeApiParaVista(
embalsesPorCuencaDesdeApi,
);

return (
<EmbalsesCuencaPod
nombreCuenca={datosCuenca.nombre}
slug={datosCuenca.slug}
embalses={embalsesPorCuenca}
/>
);
}
9 changes: 9 additions & 0 deletions front/src/app/embalse-cuenca/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { EmbalseCuencaListPod } from "@/pods/embalse-cuenca-list";
import { Metadata } from "next";

export const metadata: Metadata = {
title: "Embalses por cuencas",
};
export default function EmbalsesCuencasPage() {
return <EmbalseCuencaListPod />;
}
24 changes: 24 additions & 0 deletions front/src/common/models/cuencas.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Lookup } from "./lookup.model";

export interface CuencasModel {
id: string;
name: string;
}

export interface CuencasModelApi {
_id: string;
nombre: string;
}

export interface EmbalsesCuencaListApi {
embalse_id: string;
nombre: string;
slug: string;
cuenca: CuencasModelApi;
}

export interface EmbalsesCuencaList {
id: string;
name: string;
slug?: string;
}
1 change: 1 addition & 0 deletions front/src/common/models/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./lookup.model";
export * from "./cuencas.model";
36 changes: 36 additions & 0 deletions front/src/core/constants/cuencas.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const cuencas = {
SEGURA: { nombre: "Segura", slug: "segura" },
MINO_SIL: { nombre: "Miño - Sil", slug: "mino-sil" },
EBRO: { nombre: "Ebro", slug: "ebro" },
GUADALQUIVIR: { nombre: "Guadalquivir", slug: "guadalquivir" },
JUCAR: { nombre: "Júcar", slug: "jucar" },
DUERO: { nombre: "Duero", slug: "duero" },
CANTABRICO_ORIENTAL: {
nombre: "Cantábrico Oriental",
slug: "cantabrico-oriental",
},
CUENCA_MEDITERRANEA_ANDALUZA: {
nombre: "Cuenca Mediterránea Andaluza",
slug: "cuenca-mediterranea-andaluza",
},
GUADIANA: { nombre: "Guadiana", slug: "guadiana" },
CANTABRICO_OCCIDENTAL: {
nombre: "Cantábrico Occidental",
slug: "cantabrico-occidental",
},
TINTO_ODIEL_Y_PIEDRAS: {
nombre: "Tinto, Odiel y Piedras",
slug: "tinto-odiel-y-piedras",
},
TAJO: { nombre: "Tajo", slug: "tajo" },
GALICIA_COSTA: { nombre: "Galicia Costa", slug: "galicia-costa" },
GUADALETE_BARBATE: { nombre: "Guadalete-Barbate", slug: "guadalete-barbate" },
CUENCAS_INTERNAS_DEL_PAIS_VASCO: {
nombre: "Cuencas Internas del País Vasco",
slug: "cuencas-internas-del-pais-vasco",
},
CUENCAS_INTERNAS_DE_CATALUNA: {
nombre: "Cuencas Internas de Cataluña",
slug: "cuencas-internas-de-cataluna",
},
} as const;
6 changes: 6 additions & 0 deletions front/src/layouts/footer.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export const FooterComponent: FC = () => {
>
Embalses por provincias
</Link>
<Link
href="/embalse-cuenca"
className="link-accessible text-[15px] leading-none font-normal"
>
Embalses por cuencas
</Link>
<Link
href="/equipo"
className="link-accessible text-[15px] leading-none font-normal"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Card } from "@/common/components/card.component";
import { mapListaCuencasDesdeApiParaVista } from "./embalse-cuenca.mapper";
import { getRiverBasins } from "./embalse-cuenca-list.repository";
import Link from "next/link";
import { generateSlug } from "db-model";

export const EmbalsesCuencaList: React.FC = async () => {
const cuencasAPI = await getRiverBasins();
const cuencasList = mapListaCuencasDesdeApiParaVista(cuencasAPI);

return (
<Card className="mx-auto w-full pt-6 pr-4 pb-6 pl-4 md:max-w-225 md:p-8">
<div className="bg-base-100 rounded-2xl p-6">
<h2>Embalses por cuencas</h2>
<div className="grid grid-cols-1 gap-4 p-6 sm:grid-cols-2 md:grid-cols-3">
{cuencasList.map(({ id, name }) => (
<Link
key={id}
href={`/embalse-cuenca/${generateSlug(name)}`}
className="link-accessible"
>
{name}
</Link>
))}
</div>
</div>
</Card>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from "react";
import { EmbalsesCuencaList } from "./embalse-cuenca-list.component";

export const EmbalseCuencaListPod: React.FC = () => {
return <EmbalsesCuencaList />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use server";

import { getDb } from "@/lib/mongodb";
import type { CuencasModelApi } from "@/common/models/cuencas.model";

export async function getRiverBasins(): Promise<CuencasModelApi[]> {
try {
const db = await getDb();
const docs = await db
.collection("cuencas")
.find({}, { projection: { _id: 1, nombre: 1 } })
.toArray();

return docs.map((doc) => ({
_id: doc.slug ?? String(doc._id),
nombre: doc.nombre ?? "",
}));
} catch (error) {
console.warn(
"getEmbalsesByRiverBasin: MongoDB not available (build time?), returning empty array.",
"Error:",
error instanceof Error ? error.message : error,
);
}
return [];
}
11 changes: 11 additions & 0 deletions front/src/pods/embalse-cuenca-list/embalse-cuenca.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CuencasModel, CuencasModelApi } from "@/common/models/cuencas.model";

export const mapListaCuencasDesdeApiParaVista = (
cuencas: CuencasModelApi[],
): CuencasModel[] =>
Array.isArray(cuencas)
? cuencas.map((cuenca) => ({
id: cuenca._id,
name: cuenca.nombre,
}))
: [];
1 change: 1 addition & 0 deletions front/src/pods/embalse-cuenca-list/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./embalse-cuenca-list.pod";
42 changes: 42 additions & 0 deletions front/src/pods/embalse-cuenca/embalse-cuenca.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";
import { Card } from "@/common/components/card.component";
import { CuencasModel } from "@/common/models";
import { generateSlug } from "db-model";
import Link from "next/link";

export interface Props {
nombreCuenca: string;
slug: string;
embalses: CuencasModel[];
}

export const EmbalseCuencaComponent: React.FC<Props> = (props) => {
const { nombreCuenca, slug, embalses } = props;
return (
<Card className="mx-auto w-full pt-6 pr-4 pb-6 pl-4 md:max-w-225 md:p-8">
<div className="bg-base-100 rounded-2xl p-6">
{embalses.length === 0 ? (
<h2>No se encontraron embalses para {nombreCuenca}</h2>
) : (
<h2>Embalses de {nombreCuenca}</h2>
)}
<div className="grid grid-cols-1 gap-4 p-6 sm:grid-cols-2 md:grid-cols-3">
{embalses.map(({ id, name }) => (
<Link
key={id}
href={`/embalse/${generateSlug(name)}`}
className="link-accessible"
>
{name}
</Link>
))}
</div>
<img
className="mt-4 w-full rounded-xl md:aspect-434/171"
src="/images/embalse-generico.jpg"
alt={`Mapa de ubicación de embalses de ${nombreCuenca}`}
/>
</div>
</Card>
);
};
14 changes: 14 additions & 0 deletions front/src/pods/embalse-cuenca/embalse-cuenca.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
EmbalsesCuencaList,
EmbalsesCuencaListApi,
} from "@/common/models/cuencas.model";

export const mapRiverBasinListFromApiToView = (
embalses: EmbalsesCuencaListApi[],
): EmbalsesCuencaList[] =>
Array.isArray(embalses)
? embalses.map((embalse) => ({
id: embalse.embalse_id,
name: embalse.nombre,
}))
: [];
19 changes: 19 additions & 0 deletions front/src/pods/embalse-cuenca/embalse-cuenca.pod.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { EmbalseCuencaComponent } from "./embalse-cuenca.component";
import { CuencasModel } from "@/common/models";

export interface Props {
nombreCuenca: string;
slug: string;
embalses: CuencasModel[];
}
export const EmbalsesCuencaPod: React.FC<Props> = (props) => {
const { nombreCuenca, slug, embalses } = props;
return (
<EmbalseCuencaComponent
nombreCuenca={nombreCuenca}
slug={slug}
embalses={embalses}
/>
);
};
28 changes: 28 additions & 0 deletions front/src/pods/embalse-cuenca/embalse-cuenca.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use server";

import { getDb } from "@/lib/mongodb";
import { CuencasModelApi } from "@/common/models/cuencas.model";

export async function getEmbalsesPorCuenca(
nombre: string,
): Promise<CuencasModelApi[]> {
try {
const db = await getDb();
const docs = await db
.collection("embalses")
.find({ "cuenca.nombre": nombre }, { projection: { _id: 1, nombre: 1 } })
.toArray();

return docs.map((doc) => ({
_id: doc.slug ?? String(doc._id),
nombre: doc.nombre ?? "",
}));
} catch (error) {
console.warn(
"getEmbalsesByRiverBasin: MongoDB not available (build time?), returning empty array.",
"Error:",
error instanceof Error ? error.message : error,
);
}
return [];
}
2 changes: 2 additions & 0 deletions front/src/pods/embalse-cuenca/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./embalse-cuenca.pod";
export * from "./embalse-cuenca.repository";