Refactor card components for improved styling and icon updates

This commit is contained in:
Ariful Alam 2025-07-06 17:12:37 +06:00
parent 3d42c1fc21
commit 9c09a9d91e
6 changed files with 132 additions and 112 deletions

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import LazyImage from '../lazy-image';
import { AiOutlineContainer } from 'react-icons/ai';
import { PiNewspaper } from 'react-icons/pi';
import { getDevPost, getMediumPost } from '@arifszn/blog-js';
import { formatDistance } from 'date-fns';
import { SanitizedBlog } from '../../interfaces/sanitized-config';
@ -38,7 +38,7 @@ const BlogCard = ({
const array = [];
for (let index = 0; index < blog.limit; index++) {
array.push(
<div className="card shadow-lg card-sm bg-base-100" key={index}>
<div className="card shadow-md card-sm bg-base-100" key={index}>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col md:flex-row">
<div className="avatar mb-5 md:mb-0">
@ -95,7 +95,7 @@ const BlogCard = ({
return articles && articles.length ? (
articles.slice(0, blog.limit).map((article, index) => (
<a
className="card shadow-lg card-sm bg-base-100 cursor-pointer"
className="card shadow-md card-sm bg-base-100 cursor-pointer"
key={index}
href={article.link}
onClick={(e) => {
@ -162,7 +162,7 @@ const BlogCard = ({
))
) : (
<div className="text-center mb-6">
<AiOutlineContainer className="mx-auto h-12 w-12 opacity-30" />
<PiNewspaper className="mx-auto h-12 w-12 opacity-30" />
<p className="mt-1 text-sm opacity-50 text-base-content">
No recent post
</p>
@ -172,34 +172,38 @@ const BlogCard = ({
return (
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div
className={`card card-sm bg-base-100 ${
loading || (articles && articles.length)
? 'shadow-sm bg-opacity-40'
: 'shadow-lg'
}`}
>
<div className="card-body">
<div className="mx-3 mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ widthCls: 'w-28', heightCls: 'h-8' })
) : (
<span className="text-base-content opacity-70">
My Articles
</span>
)}
</h5>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 gap-6">
{loading || !articles ? renderSkeleton() : renderArticles()}
<div className="card bg-base-200 shadow-xl border border-base-300">
<div className="card-body p-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
<div className="flex items-center space-x-3">
{loading ? (
skeleton({
widthCls: 'w-12',
heightCls: 'h-12',
className: 'rounded-xl',
})
) : (
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
<PiNewspaper className="text-2xl" />
</div>
)}
<div className="min-w-0 flex-1">
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
{loading
? skeleton({ widthCls: 'w-28', heightCls: 'h-8' })
: 'My Articles'}
</h3>
<p className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
{loading
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
: 'Recent posts'}
</p>
</div>
</div>
</div>
<div className="grid grid-cols-1 gap-6">
{loading || !articles ? renderSkeleton() : renderArticles()}
</div>
</div>
</div>
</div>

View File

@ -1,5 +1,6 @@
import { Fragment } from 'react';
import LazyImage from '../lazy-image';
import { MdOpenInNew } from 'react-icons/md';
import { ga, skeleton } from '../../utils';
import { SanitizedExternalProject } from '../../interfaces/sanitized-config';
@ -18,7 +19,7 @@ const ExternalProjectCard = ({
const array = [];
for (let index = 0; index < externalProjects.length; index++) {
array.push(
<div className="card shadow-lg card-sm bg-base-100" key={index}>
<div className="card shadow-md card-sm bg-base-100" key={index}>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col">
<div className="w-full">
@ -69,7 +70,7 @@ const ExternalProjectCard = ({
const renderExternalProjects = () => {
return externalProjects.map((item, index) => (
<a
className="card shadow-lg card-sm bg-base-100 cursor-pointer"
className="card shadow-md card-sm bg-base-100 cursor-pointer"
key={index}
href={item.link}
onClick={(e) => {
@ -126,28 +127,38 @@ const ExternalProjectCard = ({
return (
<Fragment>
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card card-sm bg-base-100 shadow-sm bg-opacity-40">
<div className="card-body">
<div className="mx-3 flex items-center justify-between mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
) : (
<span className="text-base-content opacity-70">
{header}
</span>
)}
</h5>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderExternalProjects()}
<div className="card bg-base-200 shadow-xl border border-base-300">
<div className="card-body p-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
<div className="flex items-center space-x-3">
{loading ? (
skeleton({
widthCls: 'w-12',
heightCls: 'h-12',
className: 'rounded-xl',
})
) : (
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
<MdOpenInNew className="text-2xl" />
</div>
)}
<div className="min-w-0 flex-1">
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
{loading
? skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
: header}
</h3>
<p className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
{loading
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
: `Showcasing ${externalProjects.length} external projects`}
</p>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderExternalProjects()}
</div>
</div>
</div>
</div>

View File

@ -1,5 +1,5 @@
import { Fragment } from 'react';
import { AiOutlineFork, AiOutlineStar } from 'react-icons/ai';
import { AiOutlineFork, AiOutlineStar, AiOutlineGithub } from 'react-icons/ai';
import { MdInsertLink } from 'react-icons/md';
import { ga, getLanguageColor, skeleton } from '../../utils';
import { GithubProject } from '../../interfaces/github-project';
@ -9,14 +9,12 @@ const GithubProjectCard = ({
githubProjects,
loading,
limit,
username,
googleAnalyticsId,
}: {
header: string;
githubProjects: GithubProject[];
loading: boolean;
limit: number;
username: string;
googleAnalyticsId?: string;
}) => {
if (!loading && githubProjects.length === 0) {
@ -27,7 +25,7 @@ const GithubProjectCard = ({
const array = [];
for (let index = 0; index < limit; index++) {
array.push(
<div className="card shadow-lg card-sm bg-base-100" key={index}>
<div className="card shadow-md card-sm bg-base-100" key={index}>
<div className="flex justify-between flex-col p-8 h-full w-full">
<div>
<div className="flex items-center">
@ -76,7 +74,7 @@ const GithubProjectCard = ({
const renderProjects = () => {
return githubProjects.map((item, index) => (
<a
className="card shadow-lg card-sm bg-base-100 cursor-pointer"
className="card shadow-md card-sm bg-base-100 cursor-pointer"
href={item.html_url}
key={index}
onClick={(e) => {
@ -84,9 +82,7 @@ const GithubProjectCard = ({
try {
if (googleAnalyticsId) {
ga.event('Click project', {
project: item.name,
});
ga.event('Click project', { project: item.name });
}
} catch (error) {
console.error(error);
@ -136,40 +132,41 @@ const GithubProjectCard = ({
return (
<Fragment>
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card card-sm bg-base-100 shadow-sm bg-opacity-40">
<div className="card-body">
<div className="mx-3 flex items-center justify-between mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
) : (
<span className="text-base-content opacity-70">
{header}
</span>
)}
</h5>
{loading ? (
skeleton({ widthCls: 'w-10', heightCls: 'h-5' })
) : (
<a
href={`https://github.com/${username}?tab=repositories`}
target="_blank"
rel="noreferrer"
className="text-base-content opacity-50 hover:underline"
>
See All
</a>
)}
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderProjects()}
<div className="card bg-base-200 shadow-xl border border-base-300">
<div className="card-body p-8">
{/* Enhanced Header Section */}
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
<div className="flex items-center space-x-3">
{loading ? (
skeleton({
widthCls: 'w-12',
heightCls: 'h-12',
className: 'rounded-xl',
})
) : (
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
<AiOutlineGithub className="text-2xl" />
</div>
)}
<div className="min-w-0 flex-1">
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
{loading
? skeleton({ widthCls: 'w-48', heightCls: 'h-8' })
: header}
</h3>
<p className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
{loading
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
: `Showcasing ${githubProjects.length} featured repositories`}
</p>
</div>
</div>
</div>
{/* Projects Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderProjects()}
</div>
</div>
</div>
</div>

View File

@ -1,4 +1,5 @@
import { Fragment } from 'react';
import { AiOutlineBook } from 'react-icons/ai';
import { SanitizedPublication } from '../../interfaces/sanitized-config';
import { skeleton } from '../../utils';
@ -13,7 +14,7 @@ const PublicationCard = ({
const array = [];
for (let index = 0; index < publications.length; index++) {
array.push(
<div className="card shadow-lg card-sm bg-base-100" key={index}>
<div className="card shadow-md card-sm bg-base-100" key={index}>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col">
<div className="w-full">
@ -76,7 +77,7 @@ const PublicationCard = ({
const renderPublications = () => {
return publications.map((item, index) => (
<a
className="card shadow-lg card-sm bg-base-100 cursor-pointer"
className="card shadow-md card-sm bg-base-100 cursor-pointer"
key={index}
href={item.link}
target="_blank"
@ -120,28 +121,38 @@ const PublicationCard = ({
return (
<Fragment>
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card card-sm bg-base-100 shadow-sm bg-opacity-40">
<div className="card-body">
<div className="mx-3 flex items-center justify-between mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
) : (
<span className="text-base-content opacity-70">
Publications
</span>
)}
</h5>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderPublications()}
<div className="card bg-base-200 shadow-xl border border-base-300">
<div className="card-body p-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
<div className="flex items-center space-x-3">
{loading ? (
skeleton({
widthCls: 'w-12',
heightCls: 'h-12',
className: 'rounded-xl',
})
) : (
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
<AiOutlineBook className="text-2xl" />
</div>
)}
<div className="min-w-0 flex-1">
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
{loading
? skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
: 'Publications'}
</h3>
<p className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
{loading
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
: `Showcasing ${publications.length} publications`}
</p>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderPublications()}
</div>
</div>
</div>
</div>

View File

@ -33,14 +33,11 @@ const SkillCard = ({
</h5>
</div>
<div className="p-3 flow-root">
<div className="-m-1 flex flex-wrap justify-center">
<div className="-m-1 flex flex-wrap justify-center gap-2">
{loading
? renderSkeleton()
: skills.map((skill, index) => (
<div
key={index}
className="m-1 text-xs inline-flex items-center font-bold leading-sm px-3 py-1 badge-primary bg-opacity-90 rounded-full"
>
<div key={index} className="badge badge-primary badge-sm">
{skill}
</div>
))}

View File

@ -65,7 +65,7 @@ const ThemeChanger = ({
<div className="flex-0">
{loading ? (
skeleton({
widthCls: 'w-14 md:w-28',
widthCls: 'w-12',
heightCls: 'h-10',
className: 'mr-6',
})