website/components/BlogBlocks.tsx

154 lines
3.5 KiB
TypeScript

import { Markdown } from ':components/Markdown.tsx'
import { NewsFrontMatter } from ':src/blog/types.ts'
export type BlogProps = {
title: string
description: string
body: string
author: string
publisher: string
lastUpdate: Date
name: string
url: string
hash: string
options: NewsFrontMatter['x-cohabit']
tags: NewsFrontMatter['tags']
}
export function BlogCard(
{ title, description, author, lastUpdate, name, options, tags, publisher }:
BlogProps,
) {
return (
<div
class='components__blog_block components__blog_block--card'
style={{ backgroundImage: `url(${options.thumbnail})` }}
>
<div class='components__blog_block__spacer'></div>
<h3>
<a href={`/blog/${name}`}>{title}</a>
</h3>
<NewsLinks links={options.links} />
<NewsTags tags={tags} />
<span class='components__blog_block__publisher'>
{`@${publisher}`}
</span>
<NewsStatus status={options.status} />
<div class='components__blog_block__description'>
{description}
</div>
<NewsFooter author={author} lastUpdate={lastUpdate} />
</div>
)
}
export function BlogPost(
{
title,
description,
author,
lastUpdate,
body,
url,
options,
tags,
publisher,
}: BlogProps,
) {
return (
<div class='components__blog_block--post'>
<h1>{title}</h1>
<div class='components__blog_post__infos'>
<span class='components__blog_block__publisher'>
{`@${publisher}`}
</span>
<NewsStatus status={options.status} long />
<NewsLinks links={options.links} />
<NewsTags tags={tags} />
</div>
<div class='components__blog_post__infos'>
<span>{`Visibilité : ${options.visibility}`}</span>
<span>
{`Date de délivrance : ${new Date(options.dueDate).toLocaleString()}`}
</span>
</div>
<div class='components__blog_post__description'>
{description}
</div>
<div class='components__blog_post__body'>
<Markdown options={{ allowMath: true, baseUrl: url }}>
{body}
</Markdown>
</div>
<NewsFooter author={author} lastUpdate={lastUpdate} />
</div>
)
}
function NewsTags({ tags }: Pick<BlogProps, 'tags'>) {
return (
<div class='components__blog_block__tags'>
{tags ? tags.map((tag) => <span>{tag}</span>) : <span>Aucun tag</span>}
</div>
)
}
function NewsFooter(
{ author, lastUpdate }: Pick<BlogProps, 'author' | 'lastUpdate'>,
) {
return (
<div class='components__blog_block__footer'>
<div>
<i class='ri-quill-pen-line'></i>
<span>{author}</span>
</div>
<div>
<i class='ri-refresh-line'></i>
<span>{lastUpdate.toLocaleDateString()}</span>
</div>
</div>
)
}
function NewsLinks({ links }: Pick<BlogProps['options'], 'links'>) {
return (
<div class='components__blog_block__links'>
{links
? links.flatMap(Object.entries).map((
[name, link],
) => <a href={link} target='_blank' title={name}>{name}</a>)
: <span>Aucun lien rapide</span>}
</div>
)
}
function NewsStatus(
{ status, long = false }: Pick<BlogProps['options'], 'status'> & {
long?: boolean
},
) {
const title = status === 'canceled'
? 'Annulé'
: status === 'current'
? 'En cours'
: status === 'finished'
? 'Terminé'
: 'Prévu'
return (
<span
class='components__blog_block__status'
title={title}
>
{status === 'canceled'
? <i class='ri-calendar-close-line'></i>
: status === 'current'
? <i class='ri-calendar-2-line'></i>
: status === 'finished'
? <i class='ri-calendar-check-line'></i>
: <i class='ri-calendar-2-line'></i>}
{long ? ` ${title}` : ''}
</span>
)
}