feat: implement NewsList component and configure TinaCMS news and documentary collections
This commit is contained in:
parent
70d963770e
commit
7598808f60
|
|
@ -1,85 +1,111 @@
|
|||
---
|
||||
import { Image } from "astro:assets"
|
||||
import { Image } from "astro:assets";
|
||||
import { Icon } from "astro-icon/components";
|
||||
import "dayjs/locale/es";
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
const regionNames = new Intl.DisplayNames(['es'], { type: 'region' });
|
||||
const regionNames = new Intl.DisplayNames(["es"], { type: "region" });
|
||||
|
||||
const locale = Astro.currentLocale;
|
||||
import { createTranslator } from '@/i18n';
|
||||
import { createTranslator } from "@/i18n";
|
||||
const tl = createTranslator(Astro.currentLocale);
|
||||
dayjs.extend(utc);
|
||||
dayjs.locale(locale);
|
||||
|
||||
const { data, content } = Astro.props;
|
||||
const nicedate = dayjs.utc(data.data.date).format("D MMMM YYYY");
|
||||
const countryName = data?.data?.country ? regionNames.of(data.data.country) : "";
|
||||
const countryName = data?.data?.country
|
||||
? regionNames.of(data.data.country)
|
||||
: "";
|
||||
|
||||
const locationArray = [data.data.city,countryName]
|
||||
const location = locationArray.filter(Boolean).join(', ');
|
||||
const locationArray = [data.data.city, countryName];
|
||||
const location = locationArray.filter(Boolean).join(", ");
|
||||
|
||||
const newsUrl = `/${locale}/news/${data.id}`;
|
||||
|
||||
const rawContent = content?.body || "";
|
||||
const plainText = rawContent
|
||||
.replace(/^#.*$/gm, '')
|
||||
.replace(/^###.*$/gm, '')
|
||||
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
||||
.replace(/\*([^*]+)\*/g, '$1')
|
||||
.replace(/_([^_]+)_/g, '$1')
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
.replace(/^>.*$/gm, '')
|
||||
.replace(/`[^`]+`/g, '')
|
||||
.replace(/^[-*]\s+/gm, '')
|
||||
.trim();
|
||||
const words = plainText.split(/\s+/).filter(w => w.length > 0).slice(0, 40);
|
||||
const excerpt = words.join(' ') + (words.length === 40 ? '...' : '');
|
||||
.replace(/^#.*$/gm, "")
|
||||
.replace(/^###.*$/gm, "")
|
||||
.replace(/\*\*([^*]+)\*\*/g, "$1")
|
||||
.replace(/\*([^*]+)\*/g, "$1")
|
||||
.replace(/_([^_]+)_/g, "$1")
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
||||
.replace(/^>.*$/gm, "")
|
||||
.replace(/`[^`]+`/g, "")
|
||||
.replace(/^[-*]\s+/gm, "")
|
||||
.trim();
|
||||
const words = plainText
|
||||
.split(/\s+/)
|
||||
.filter((w) => w.length > 0)
|
||||
.slice(0, 40);
|
||||
const excerpt = words.join(" ") + (words.length === 40 ? "..." : "");
|
||||
---
|
||||
|
||||
<a href={newsUrl} class="block group">
|
||||
<article class="flex flex-col md:flex-row gap-6 md:gap-8 p-4 md:p-6 border-b border-tertiary/20 hover:bg-tertiary/5 transition-colors">
|
||||
<article
|
||||
class="flex flex-col md:flex-row gap-6 md:gap-8 p-4 md:p-6 border-b border-tertiary/20 hover:bg-tertiary/5 transition-colors"
|
||||
>
|
||||
<div class="md:w-1/3 flex-shrink-0 overflow-hidden">
|
||||
<Image
|
||||
src={data.data.thumbnail}
|
||||
src={data.data.thumbnail_square || data.data.thumbnail}
|
||||
alt={data.data.title}
|
||||
width={400}
|
||||
height={300}
|
||||
width={480}
|
||||
height={340}
|
||||
class="w-full h-48 md:h-full object-cover transform group-hover:scale-105 transition-transform duration-300"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="md:w-2/3 flex flex-col">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="font-normal font-primary text-sm text-tertiary/70">{nicedate}</span>
|
||||
{location && (
|
||||
<>
|
||||
<span class="text-tertiary/40">|</span>
|
||||
<span class="font-normal font-primary text-sm text-tertiary/70">{location}</span>
|
||||
</>
|
||||
)}
|
||||
<span class="font-normal font-primary text-sm text-tertiary/70"
|
||||
>{nicedate}
|
||||
</span>
|
||||
{
|
||||
location && (
|
||||
<>
|
||||
<span class="text-tertiary/40">|</span>
|
||||
<span class="font-normal font-primary text-sm text-tertiary/70">
|
||||
{location}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl md:text-2xl font-bold font-secondary text-tertiary group-hover:text-tertiary/80 transition-colors mb-2">
|
||||
<h3
|
||||
class="text-xl md:text-2xl font-bold font-secondary text-tertiary group-hover:text-tertiary/80 transition-colors mb-2"
|
||||
>
|
||||
{data.data.title}
|
||||
</h3>
|
||||
|
||||
<p class="font-primary text-base text-tertiary/80 mb-4 line-clamp-3">
|
||||
<p
|
||||
class="font-primary text-base text-tertiary/80 mb-4 line-clamp-3"
|
||||
>
|
||||
{excerpt}
|
||||
</p>
|
||||
|
||||
{data.data.tags && data.data.tags.length > 0 && (
|
||||
<div class="flex flex-nowrap md:flex-wrap gap-2 overflow-x-auto md:overflow-visible pb-2 md:pb-0 mb-4">
|
||||
{data.data.tags.map((tag: string) => (
|
||||
<span class="badge rounded-none bg-[#EBE6D2] border-none text-[#003421] whitespace-nowrap">{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
data.data.tags && data.data.tags.length > 0 && (
|
||||
<div class="flex flex-nowrap md:flex-wrap gap-2 overflow-x-auto md:overflow-visible pb-2 md:pb-0 mb-4">
|
||||
{data.data.tags.map((tag: string) => (
|
||||
<span class="badge rounded-none bg-[#EBE6D2] border-none text-[#003421] whitespace-nowrap">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div class="mt-auto">
|
||||
<span class="inline-flex items-center gap-1 text-sm font-primary text-tertiary font-semibold group-hover:underline">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 text-sm font-primary text-tertiary font-semibold group-hover:underline"
|
||||
>
|
||||
{tl("news.seemore")}
|
||||
<Icon name="ph:arrow-right" class="transform group-hover:translate-x-1 transition-transform" />
|
||||
<Icon
|
||||
name="ph:arrow-right"
|
||||
class="transform group-hover:translate-x-1 transition-transform"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const news = defineCollection({
|
|||
state: z.string().optional(),
|
||||
country: z.string().optional(),
|
||||
thumbnail: image().optional().describe("Main news thumbnail image"),
|
||||
thumbnail_square: image().optional().describe("Main news thumbnail square image"),
|
||||
youtube: z.string().optional(),
|
||||
tags: z.array(z.string()).optional().describe("News tags"),
|
||||
gallery: z.array(z.object({
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ date: 2025-01-04
|
|||
slug: 2025-01-04-jerusalen-en-el-centro-del-2025-advertencias-sobre-un-ano-clave-para-el-cambio-global
|
||||
place: ''
|
||||
country: 'PR'
|
||||
city: 'Puerto Rico'
|
||||
city: 'Cayey '
|
||||
thumbnail_square: 'https://ik.imagekit.io/crpy/7K0B4402-1.webp?tr=w-1280,q-auto,f-auto'
|
||||
thumbnail: 'https://ik.imagekit.io/crpy/7K0B4402.webp?tr=w-1280,q-auto,f-auto'
|
||||
tags: [Israel, Puerto Rico]
|
||||
gallery: [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ date: 2025-02-16
|
|||
slug: 2025-02-16-llamado-a-la-accion-internacional-el-dr-jose-benjamin-perez-matos-exige-respuestas-concretas-ante-las-crisis-en-israel-y-venezuela
|
||||
place: ''
|
||||
country: 'PR'
|
||||
city: 'Puerto Rico'
|
||||
city: 'Cayey'
|
||||
thumbnail: 'https://ik.imagekit.io/crpy/tr:w-1280/comunicado-1.webp'
|
||||
tags: [Puerto Rico, Venezuela, Israel]
|
||||
gallery: [
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":{"fullVersion":"2.2.5","major":"2","minor":"2","patch":"5"},"meta":{"flags":["experimentalData"]},"collections":[{"name":"news","label":"News","path":"src/content/news","format":"md","fields":[{"type":"string","name":"locale","label":"Language","options":[{"label":"Español","value":"es"},{"label":"English","value":"en"},{"label":"Português","value":"pt"},{"label":"Kinyarwanda","value":"rw"}],"namespace":["news","locale"],"searchable":true,"uid":false},{"type":"string","name":"title","label":"Title","isTitle":true,"required":true,"namespace":["news","title"],"searchable":true,"uid":false},{"type":"datetime","name":"date","label":"Date","required":true,"namespace":["news","date"],"searchable":true,"uid":false},{"type":"string","name":"slug","label":"Slug","namespace":["news","slug"],"searchable":true,"uid":false},{"type":"string","name":"place","label":"Place","namespace":["news","place"],"searchable":true,"uid":false},{"type":"string","name":"thumbnail","label":"Thumbnail URL","namespace":["news","thumbnail"],"searchable":true,"uid":false},{"type":"string","name":"youtube","label":"YouTube ID","namespace":["news","youtube"],"searchable":true,"uid":false},{"type":"string","name":"tags","label":"Tags (comma separated)","namespace":["news","tags"],"searchable":true,"uid":false},{"type":"boolean","name":"draft","label":"Draft","namespace":["news","draft"],"searchable":true,"uid":false},{"type":"rich-text","name":"body","label":"Content","isBody":true,"namespace":["news","body"],"searchable":true,"parser":{"type":"markdown"},"uid":false}],"namespace":["news"]},{"name":"documentaries","label":"Documentaries","path":"src/content/documentaries","format":"md","fields":[{"type":"string","name":"locale","label":"Language","options":[{"label":"Español","value":"es"},{"label":"English","value":"en"},{"label":"Português","value":"pt"},{"label":"Kinyarwanda","value":"rw"}],"namespace":["documentaries","locale"],"searchable":true,"uid":false},{"type":"string","name":"title","label":"Title","isTitle":true,"required":true,"namespace":["documentaries","title"],"searchable":true,"uid":false},{"type":"string","name":"video_yt","label":"YouTube ID","namespace":["documentaries","video_yt"],"searchable":true,"uid":false},{"type":"datetime","name":"date","label":"Date","required":true,"namespace":["documentaries","date"],"searchable":true,"uid":false}],"namespace":["documentaries"]}],"config":{"media":{"tina":{"publicFolder":"public","mediaRoot":"public/images"}}}}
|
||||
{"version":{"fullVersion":"2.2.5","major":"2","minor":"2","patch":"5"},"meta":{"flags":["experimentalData"]},"collections":[{"name":"news","label":"News","path":"src/content/news","format":"md","fields":[{"type":"string","name":"locale","label":"Language","options":[{"label":"Español","value":"es"},{"label":"English","value":"en"},{"label":"Português","value":"pt"},{"label":"Kinyarwanda","value":"rw"}],"namespace":["news","locale"],"searchable":true,"uid":false},{"type":"string","name":"title","label":"Title","isTitle":true,"required":true,"namespace":["news","title"],"searchable":true,"uid":false},{"type":"datetime","name":"date","label":"Date","required":true,"namespace":["news","date"],"searchable":true,"uid":false},{"type":"string","name":"slug","label":"Slug","namespace":["news","slug"],"searchable":true,"uid":false},{"type":"string","name":"place","label":"Place","namespace":["news","place"],"searchable":true,"uid":false},{"type":"string","name":"thumbnail","label":"Thumbnail URL","namespace":["news","thumbnail"],"searchable":true,"uid":false},{"type":"string","name":"thumbnail_square","label":"Thumbnail Square URL","namespace":["news","thumbnail_square"],"searchable":true,"uid":false},{"type":"string","name":"youtube","label":"YouTube ID","namespace":["news","youtube"],"searchable":true,"uid":false},{"type":"string","name":"tags","label":"Tags (comma separated)","namespace":["news","tags"],"searchable":true,"uid":false},{"type":"boolean","name":"draft","label":"Draft","namespace":["news","draft"],"searchable":true,"uid":false},{"type":"rich-text","name":"body","label":"Content","isBody":true,"namespace":["news","body"],"searchable":true,"parser":{"type":"markdown"},"uid":false}],"namespace":["news"]},{"name":"documentaries","label":"Documentaries","path":"src/content/documentaries","format":"md","fields":[{"type":"string","name":"locale","label":"Language","options":[{"label":"Español","value":"es"},{"label":"English","value":"en"},{"label":"Português","value":"pt"},{"label":"Kinyarwanda","value":"rw"}],"namespace":["documentaries","locale"],"searchable":true,"uid":false},{"type":"string","name":"title","label":"Title","isTitle":true,"required":true,"namespace":["documentaries","title"],"searchable":true,"uid":false},{"type":"string","name":"video_yt","label":"YouTube ID","namespace":["documentaries","video_yt"],"searchable":true,"uid":false},{"type":"datetime","name":"date","label":"Date","required":true,"namespace":["documentaries","date"],"searchable":true,"uid":false}],"namespace":["documentaries"]}],"config":{"media":{"tina":{"publicFolder":"public","mediaRoot":"public/images"}}}}
|
||||
|
|
@ -62,6 +62,11 @@ var config_default = defineConfig({
|
|||
name: "thumbnail",
|
||||
label: "Thumbnail URL"
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
name: "thumbnail_square",
|
||||
label: "Thumbnail Square URL"
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
name: "youtube",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ fragment NewsParts on News {
|
|||
slug
|
||||
place
|
||||
thumbnail
|
||||
thumbnail_square
|
||||
youtube
|
||||
tags
|
||||
draft
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ type News implements Node & Document {
|
|||
slug: String
|
||||
place: String
|
||||
thumbnail: String
|
||||
thumbnail_square: String
|
||||
youtube: String
|
||||
tags: String
|
||||
draft: Boolean
|
||||
|
|
@ -139,6 +140,7 @@ input NewsFilter {
|
|||
slug: StringFilter
|
||||
place: StringFilter
|
||||
thumbnail: StringFilter
|
||||
thumbnail_square: StringFilter
|
||||
youtube: StringFilter
|
||||
tags: StringFilter
|
||||
draft: BooleanFilter
|
||||
|
|
@ -214,6 +216,7 @@ input NewsMutation {
|
|||
slug: String
|
||||
place: String
|
||||
thumbnail: String
|
||||
thumbnail_square: String
|
||||
youtube: String
|
||||
tags: String
|
||||
draft: Boolean
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ export type News = Node & Document & {
|
|||
slug?: Maybe<Scalars['String']['output']>;
|
||||
place?: Maybe<Scalars['String']['output']>;
|
||||
thumbnail?: Maybe<Scalars['String']['output']>;
|
||||
thumbnail_square?: Maybe<Scalars['String']['output']>;
|
||||
youtube?: Maybe<Scalars['String']['output']>;
|
||||
tags?: Maybe<Scalars['String']['output']>;
|
||||
draft?: Maybe<Scalars['Boolean']['output']>;
|
||||
|
|
@ -233,6 +234,7 @@ export type NewsFilter = {
|
|||
slug?: InputMaybe<StringFilter>;
|
||||
place?: InputMaybe<StringFilter>;
|
||||
thumbnail?: InputMaybe<StringFilter>;
|
||||
thumbnail_square?: InputMaybe<StringFilter>;
|
||||
youtube?: InputMaybe<StringFilter>;
|
||||
tags?: InputMaybe<StringFilter>;
|
||||
draft?: InputMaybe<BooleanFilter>;
|
||||
|
|
@ -371,6 +373,7 @@ export type NewsMutation = {
|
|||
slug?: InputMaybe<Scalars['String']['input']>;
|
||||
place?: InputMaybe<Scalars['String']['input']>;
|
||||
thumbnail?: InputMaybe<Scalars['String']['input']>;
|
||||
thumbnail_square?: InputMaybe<Scalars['String']['input']>;
|
||||
youtube?: InputMaybe<Scalars['String']['input']>;
|
||||
tags?: InputMaybe<Scalars['String']['input']>;
|
||||
draft?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
|
|
@ -384,7 +387,7 @@ export type DocumentariesMutation = {
|
|||
date?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type NewsPartsFragment = { __typename: 'News', locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null };
|
||||
export type NewsPartsFragment = { __typename: 'News', locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, thumbnail_square?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null };
|
||||
|
||||
export type DocumentariesPartsFragment = { __typename: 'Documentaries', locale?: string | null, title: string, video_yt?: string | null, date: string };
|
||||
|
||||
|
|
@ -393,7 +396,7 @@ export type NewsQueryVariables = Exact<{
|
|||
}>;
|
||||
|
||||
|
||||
export type NewsQuery = { __typename?: 'Query', news: { __typename: 'News', id: string, locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null, _sys: { __typename?: 'SystemInfo', filename: string, basename: string, hasReferences?: boolean | null, breadcrumbs: Array<string>, path: string, relativePath: string, extension: string } } };
|
||||
export type NewsQuery = { __typename?: 'Query', news: { __typename: 'News', id: string, locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, thumbnail_square?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null, _sys: { __typename?: 'SystemInfo', filename: string, basename: string, hasReferences?: boolean | null, breadcrumbs: Array<string>, path: string, relativePath: string, extension: string } } };
|
||||
|
||||
export type NewsConnectionQueryVariables = Exact<{
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
|
|
@ -405,7 +408,7 @@ export type NewsConnectionQueryVariables = Exact<{
|
|||
}>;
|
||||
|
||||
|
||||
export type NewsConnectionQuery = { __typename?: 'Query', newsConnection: { __typename?: 'NewsConnection', totalCount: number, pageInfo: { __typename?: 'PageInfo', hasPreviousPage: boolean, hasNextPage: boolean, startCursor: string, endCursor: string }, edges?: Array<{ __typename?: 'NewsConnectionEdges', cursor: string, node?: { __typename: 'News', id: string, locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null, _sys: { __typename?: 'SystemInfo', filename: string, basename: string, hasReferences?: boolean | null, breadcrumbs: Array<string>, path: string, relativePath: string, extension: string } } | null } | null> | null } };
|
||||
export type NewsConnectionQuery = { __typename?: 'Query', newsConnection: { __typename?: 'NewsConnection', totalCount: number, pageInfo: { __typename?: 'PageInfo', hasPreviousPage: boolean, hasNextPage: boolean, startCursor: string, endCursor: string }, edges?: Array<{ __typename?: 'NewsConnectionEdges', cursor: string, node?: { __typename: 'News', id: string, locale?: string | null, title: string, date: string, slug?: string | null, place?: string | null, thumbnail?: string | null, thumbnail_square?: string | null, youtube?: string | null, tags?: string | null, draft?: boolean | null, body?: any | null, _sys: { __typename?: 'SystemInfo', filename: string, basename: string, hasReferences?: boolean | null, breadcrumbs: Array<string>, path: string, relativePath: string, extension: string } } | null } | null> | null } };
|
||||
|
||||
export type DocumentariesQueryVariables = Exact<{
|
||||
relativePath: Scalars['String']['input'];
|
||||
|
|
@ -435,6 +438,7 @@ export const NewsPartsFragmentDoc = gql`
|
|||
slug
|
||||
place
|
||||
thumbnail
|
||||
thumbnail_square
|
||||
youtube
|
||||
tags
|
||||
draft
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@ export default defineConfig({
|
|||
name: "thumbnail",
|
||||
label: "Thumbnail URL",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
name: "thumbnail_square",
|
||||
label: "Thumbnail Square URL",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
name: "youtube",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue