update project api and page, set pagination in blog and create content generator component, create blog single page, ui fix
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
IContentData,
|
||||
IContentDataLink,
|
||||
IContentImage,
|
||||
IDynamicContent,
|
||||
} from '@/models/dynamicContent';
|
||||
|
||||
function ImageContent(data: IContentImage) {
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<img
|
||||
src={data.src}
|
||||
alt={data.alt}
|
||||
className="mx-auto max-h-[60vh] max-w-[90vw] overflow-hidden rounded-2xl object-cover"
|
||||
/>
|
||||
{data.thumbTitle ? (
|
||||
<h5 className="text-center text-sm text-gray-400">{data.thumbTitle}</h5>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function titleContent(data: string) {
|
||||
return <h2 className="text-2xl font-bold text-gray-500">{data}</h2>;
|
||||
}
|
||||
|
||||
function fullContent(data: IContentData) {
|
||||
const splittedData = data.data?.split('\n') || [];
|
||||
return splittedData.map((e) => {
|
||||
return (
|
||||
<p className="indent-5 text-base text-gray-400">
|
||||
{generateLinkedContent(e, data.links)}
|
||||
</p>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function generateLinkedContent(data: string, links?: IContentDataLink[]) {
|
||||
const splitted = data.split(' ');
|
||||
|
||||
const mappedLinks = {} as Record<string, IContentDataLink>;
|
||||
links?.forEach((link) => {
|
||||
mappedLinks[link.key] = link;
|
||||
});
|
||||
|
||||
return (
|
||||
<p>
|
||||
{splitted.map((data) => {
|
||||
return mappedLinks[data] ? (
|
||||
<strong>
|
||||
<a
|
||||
href={mappedLinks[data].link}
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{mappedLinks[data].label}
|
||||
</a>{' '}
|
||||
</strong>
|
||||
) : (
|
||||
<>{data} </>
|
||||
);
|
||||
})}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
function listContent(data: string[], type: 'bullet' | 'numberList') {
|
||||
return (
|
||||
<ul>
|
||||
{data.map((item, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={`list-inside ${type === 'bullet' ? 'list-disc' : 'list-decimal'} text-sm text-gray-400`}
|
||||
>
|
||||
<h4 className="inline text-sm">{item}</h4>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ContentGenerator({
|
||||
data,
|
||||
className,
|
||||
}: {
|
||||
data: IDynamicContent[];
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className={`flex flex-col gap-3 md:gap-6 ${className}`}>
|
||||
{data.map((e) => {
|
||||
switch (e.type) {
|
||||
case 'title':
|
||||
return titleContent(e.data as string);
|
||||
case 'content':
|
||||
return <div>{fullContent(e.data as IContentData)}</div>;
|
||||
case 'image':
|
||||
return ImageContent(e.data as IContentImage);
|
||||
case 'bullet':
|
||||
case 'numberList':
|
||||
return listContent(e.data as string[], e.type);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user