This commit is contained in:
Iliyan Angelov
2025-10-08 13:46:46 +03:00
parent d48c54e2c5
commit 18ae8b9f88
94 changed files with 8882 additions and 1682 deletions

View File

@@ -1,13 +1,73 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import PostFilterItems from "./post-filter/PostFilterItems";
const BlogItems = () => {
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const postsPerPage = 6;
const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page);
// Scroll to top of posts section
window.scrollTo({ top: 0, behavior: 'smooth' });
}
};
const handleTotalPagesChange = (total: number) => {
setTotalPages(total);
};
// Generate page numbers to display
const getPageNumbers = () => {
const pages: (number | string)[] = [];
const maxPagesToShow = 5;
if (totalPages <= maxPagesToShow) {
// Show all pages if total is small
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
// Show first page
pages.push(1);
// Calculate range around current page
let startPage = Math.max(2, currentPage - 1);
let endPage = Math.min(totalPages - 1, currentPage + 1);
// Add ellipsis after first page if needed
if (startPage > 2) {
pages.push('...');
}
// Add pages around current page
for (let i = startPage; i <= endPage; i++) {
pages.push(i);
}
// Add ellipsis before last page if needed
if (endPage < totalPages - 1) {
pages.push('...');
}
// Show last page
if (totalPages > 1) {
pages.push(totalPages);
}
}
return pages;
};
return (
<section className="fix-top pb-120 blog-m">
<div className="container">
<div className="row align-items-center vertical-column-gap">
<div className="col-12 col-lg-7">
<h2 className="mt-8 fw-7 text-secondary title-anim">Blog</h2>
<h2 className="mt-8 fw-7 text-secondary title-anim">Latest Company Insights</h2>
</div>
<div className="col-12 col-lg-5">
<form action="#" method="post" autoComplete="off">
@@ -30,36 +90,58 @@ const BlogItems = () => {
</form>
</div>
</div>
<PostFilterItems />
<div className="row mt-60">
<div className="col-12">
<div className="section__cta">
<ul className="pagination">
<li>
<button>
<i className="fa-solid fa-angle-left"></i>
</button>
</li>
<li>
<Link href="blog">1</Link>
</li>
<li>
<Link href="blog" className="active">
2
</Link>
</li>
<li>
<Link href="blog">3</Link>
</li>
<li>
<button>
<i className="fa-solid fa-angle-right"></i>
</button>
</li>
</ul>
<PostFilterItems
currentPage={currentPage}
onPageChange={handlePageChange}
onTotalPagesChange={handleTotalPagesChange}
postsPerPage={postsPerPage}
/>
{totalPages > 1 && (
<div className="row mt-60">
<div className="col-12">
<div className="section__cta">
<ul className="pagination">
<li>
<button
onClick={() => handlePageChange(currentPage - 1)}
disabled={currentPage === 1}
aria-label="Previous page"
style={{ opacity: currentPage === 1 ? 0.5 : 1, cursor: currentPage === 1 ? 'not-allowed' : 'pointer' }}
>
<i className="fa-solid fa-angle-left"></i>
</button>
</li>
{getPageNumbers().map((page, index) => (
<li key={index}>
{typeof page === 'number' ? (
<button
onClick={() => handlePageChange(page)}
className={currentPage === page ? 'active' : ''}
aria-label={`Go to page ${page}`}
aria-current={currentPage === page ? 'page' : undefined}
>
{page}
</button>
) : (
<span style={{ padding: '0 10px' }}>{page}</span>
)}
</li>
))}
<li>
<button
onClick={() => handlePageChange(currentPage + 1)}
disabled={currentPage === totalPages}
aria-label="Next page"
style={{ opacity: currentPage === totalPages ? 0.5 : 1, cursor: currentPage === totalPages ? 'not-allowed' : 'pointer' }}
>
<i className="fa-solid fa-angle-right"></i>
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
)}
</div>
</section>
);

View File

@@ -1,207 +1,289 @@
"use client";
import { useParams } from "next/navigation";
import Image from "next/legacy/image";
import Link from "next/link";
import poster from "@/public/images/blog/blog-poster.png";
import info from "@/public/images/blog/blog-info.png";
import { useBlogPost } from "@/lib/hooks/useBlog";
import { getValidImageUrl, getValidImageAlt, FALLBACK_IMAGES } from "@/lib/imageUtils";
const BlogSingle = () => {
return (
<section className="tp-post-details fix-top pb-120 fade-wrapper">
<div className="container">
<div className="row">
<div className="col-12">
<div className="tp-post-intro">
<h2 className="title-anim text-xxl fw-7 text-secondary mt-8">
Tackling data of annotation problems in healthcare
</h2>
<div className="mt-60 mb-24 d-flex align-items-center justify-content-between tppr">
<div className="d-flex align-items-center tp-post-tags-container mt-8">
<p className="text-xs">Scope:</p>
<div className="d-flex align-items-center tp-post-tags">
<Link href="blog">AI</Link>
<span></span>
<Link href="blog">Artificial Intelligence</Link>
<span></span>
<Link href="blog">Data Science</Link>
<span></span>
<Link href="blog">Machine Learning</Link>
</div>
const params = useParams();
const slug = params?.slug as string;
const { post, loading, error } = useBlogPost(slug);
if (loading) {
return (
<section className="blog-single-section fix-top pb-120">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10 col-xl-8">
<div className="loading-state text-center py-5">
<div className="spinner-border text-primary mb-3" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="tp-post-meta mt-8">
<p className="author text-xs text-tertiary">Denial Lio</p>
<span></span>
<p className="date text-xs text-tertiary">18 Dec 2022</p>
</div>
</div>
<div className="tp-post-poster fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={poster}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</div>
<div className="group mt-60">
<p className="cur-lg mb-24">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
nec tortor id erat faucibus tempor id eget turpis. Donec
lobortis et neque eget congue. Mauris laoreet orci ac dictum
interdum. Sed dapibus convallis arcu, a aliquam purus sodales
nec. Integer consequat et magna sit amet porta. Maecenas
consectetur eros sed risus porta convallis eget et massa.
Integer auctor convallis ligula, sit amet sollicitudin justo
tincidunt a. Sed tellus diam.
</p>
<p className="cur-lg mb-24 fw-6">
Bibendum tincidunt orci vel, sollicitudin bibendum ligula.
Pellentesque sollicitudin nulla felis, a ornare tellus
tristique ac. Proin ultricies a turpis sit amet lacinia. Ut
laoreet nunc leo, ac congue enim laoreet in. Aenean suscipit
arcu at ligula tempor porta.
</p>
<p className="cur-lg">
Quisque et fringilla lacus, quis luctus elit. Curabitur eu dui
mattis turpis commodo eleifend. Sed porta ornare nunc et
tristique. Curabitur vel eros a ante cursus lacinia. Nam nisl
leo, aliquet a placerat at, porttitor quis augue. Proin quis
aliquet libero. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Vestibulum
varius a ipsum ornare blandit. Integer vitae eleifend risus,
id tincidunt elit. Integer tincidunt ipsum vitae sagittis
porta. Aenean ut facilisis dui. Praesent at ultricies purus.
Nam a arcu vel diam ullamcorper tincidunt. Curabitur
vestibulum commodo erat non laoreet. Proin nibh nibh,
scelerisque a nibh nec, scelerisque convallis leo. Nunc eget
elit nunc.
</p>
</div>
<div className="group-info mt-60">
<div className="row align-items-center vertical-column-gap">
<div className="col-12 col-lg-6">
<div className="fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={info}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<p className="cur-lg mb-24">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec nec tortor id erat faucibus tempor id eget turpis.
Donec lobortis et neque eget congue. Mauris laoreet orci
ac dictum interdum. Sed dapibus convallis arcu, a aliquam
purus sodales nec.
</p>
<p className="cur-lg">
Quisque et fringilla lacus, quis luctus elit. Curabitur eu
dui mattis turpis commodo eleifend. Sed porta ornare nunc
et tristique. Curabitur vel eros a ante cursus lacinia.
Nam nisl leo, aliquet a placerat at, porttitor quis augue.
Proin quis aliquet libero. Pellentesque habitant morbi
tristique senectus et netus et malesuada fames ac turpis
egestas. Vestibulum varius a ipsum ornare blandit.
</p>
</div>
</div>
</div>
<div className="group mt-60">
<h4 className="mt-8 fw-7 text-secondary title-anim mb-24">
The Hidden Markov Model&apos;s Limitations
</h4>
<p className="cur-lg mb-24">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
nec tortor id erat faucibus tempor id eget turpis. Donec
lobortis et neque eget congue. Mauris laoreet orci ac dictum
interdum. Sed dapibus convallis arcu, a aliquam purus sodales
nec.
</p>
<p className="cur-lg">
Quisque et fringilla lacus, quis luctus elit. Curabitur eu dui
mattis turpis commodo eleifend. Sed porta ornare nunc et
tristique. Curabitur vel eros a ante cursus lacinia. Nam nisl
leo, aliquet a placerat at, porttitor quis augue. Proin quis
aliquet libero. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Vestibulum
varius a ipsum ornare blandit.
</p>
</div>
<div className="group mt-60">
<h4 className="mt-8 fw-7 text-secondary title-anim mb-24">
The Effect
</h4>
<p className="cur-lg mb-24">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
nec tortor id erat faucibus tempor id eget turpis. Donec
lobortis et neque eget congue. Mauris laoreet orci ac dictum
interdum. Sed dapibus convallis arcu, a aliquam purus sodales
nec.
</p>
<p className="cur-lg">
Quisque et fringilla lacus, quis luctus elit. Curabitur eu dui
mattis turpis commodo eleifend. Sed porta ornare nunc et
tristique. Curabitur vel eros a ante cursus lacinia. Nam nisl
leo, aliquet a placerat at, porttitor quis augue. Proin quis
aliquet libero. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Vestibulum
varius a ipsum ornare blandit.
</p>
<p className="text-tertiary">Loading insight...</p>
</div>
</div>
</div>
</div>
<div className="row mt-80">
<div className="col-12">
<div className="bd-social">
<p className="fw-5 text-uppercase">Share :</p>
<ul className=" social">
<li>
<Link
href="https://www.facebook.com/"
target="_blank"
aria-label="share us on facebook"
>
<i className="fa-brands fa-facebook-f"></i>
</Link>
</li>
<li>
<Link
href="https://www.twitter.com/"
target="_blank"
aria-label="share us on twitter"
>
<i className="fa-brands fa-twitter"></i>
</Link>
</li>
<li>
<Link
href="https://www.pinterest.com/"
target="_blank"
aria-label="share us on pinterest"
>
<i className="fa-brands fa-linkedin-in"></i>
</Link>
</li>
<li>
<Link
href="https://www.instagram.com/"
target="_blank"
aria-label="share us on instagram"
>
<i className="fa-brands fa-instagram"></i>
</Link>
</li>
</ul>
</section>
);
}
if (error || !post) {
return (
<section className="blog-single-section fix-top pb-120">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10 col-xl-8">
<div className="error-state text-center py-5">
<div className="error-icon mb-4">
<i className="fa-solid fa-exclamation-circle fa-4x text-tertiary"></i>
</div>
<h2 className="text-secondary mb-3">Insight Not Found</h2>
<p className="text-tertiary mb-4">
The insight you're looking for doesn't exist or has been removed.
</p>
<Link href="/insights" className="btn btn-primary">
<i className="fa-solid fa-arrow-left me-2"></i>
Back to Insights
</Link>
</div>
</div>
</div>
</div>
</section>
);
}
return (
<section className="blog-single-section fix-top pb-120">
<div className="container">
{/* Article Content */}
<div className="row">
<div className="col-12">
<article className="blog-single-article">
{/* Article Header */}
<header className="article-header">
{/* Top Meta Bar */}
<div className="article-top-meta d-flex flex-wrap align-items-center justify-content-between mb-4">
<div className="left-meta d-flex align-items-center gap-3">
{/* Category Badge */}
{post.category && (
<Link href={`/insights?category=${post.category.slug}`} className="category-badge">
<i className="fa-solid fa-folder-open me-2"></i>
{post.category.title}
</Link>
)}
{/* Date */}
<div className="meta-item d-flex align-items-center">
<i className="fa-solid fa-calendar me-2"></i>
<span>
{new Date(post.published_at || post.created_at).toLocaleDateString('en-US', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</span>
</div>
</div>
<div className="right-meta d-flex align-items-center gap-3">
{/* Reading Time */}
<div className="meta-item d-flex align-items-center">
<i className="fa-solid fa-clock me-2"></i>
<span>{post.reading_time} min</span>
</div>
{/* Views */}
<div className="meta-item d-flex align-items-center">
<i className="fa-solid fa-eye me-2"></i>
<span>{post.views_count}</span>
</div>
</div>
</div>
{/* Title */}
<h1 className="article-title">
{post.title}
</h1>
{/* Author and Tags Bar */}
<div className="article-bottom-meta d-flex flex-wrap align-items-center justify-content-between mt-4 pt-4">
{/* Author */}
<div className="author-meta d-flex align-items-center">
<div className="author-avatar me-3">
{post.author?.avatar ? (
<Image
src={post.author.avatar}
alt={post.author.name}
width={48}
height={48}
className="rounded-circle"
/>
) : (
<div className="avatar-placeholder">
<i className="fa-solid fa-user"></i>
</div>
)}
</div>
<div className="author-info">
<div className="author-label">Written by</div>
<div className="author-name">
{post.author?.name || post.author_name || 'Admin'}
</div>
</div>
</div>
{/* Tags */}
{post.tags && post.tags.length > 0 && (
<div className="article-tags d-flex flex-wrap align-items-center gap-2">
{post.tags.map((tag) => (
<Link
key={tag.id}
href={`/insights?tag=${tag.slug}`}
className="tag-badge"
>
#{tag.name}
</Link>
))}
</div>
)}
</div>
</header>
{/* Featured Image */}
{(post.featured_image || post.thumbnail) && (
<div className="article-featured-image">
<div className="image-wrapper">
<Image
src={getValidImageUrl(
post.featured_image || post.thumbnail,
FALLBACK_IMAGES.BLOG
)}
alt={getValidImageAlt(post.title)}
width={1200}
height={600}
layout="responsive"
className="featured-image"
/>
</div>
</div>
)}
{/* Article Body */}
<div className="article-body">
{/* Excerpt */}
{post.excerpt && (
<div className="article-excerpt">
<p className="lead">{post.excerpt}</p>
</div>
)}
{/* Content */}
{post.content && (
<div
className="article-content enterprise-content"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
)}
</div>
{/* Footer Section */}
<footer className="article-footer">
{/* Share Section */}
<div className="article-share">
<div className="share-container">
<h6 className="share-title">
Share this insight
</h6>
<div className="social-share">
<Link
href={`https://www.linkedin.com/shareArticle?mini=true&url=${typeof window !== 'undefined' ? encodeURIComponent(window.location.href) : ''}&title=${encodeURIComponent(post.title)}`}
target="_blank"
rel="noopener noreferrer"
className="share-btn share-linkedin"
aria-label="Share on LinkedIn"
>
<i className="fa-brands fa-linkedin-in"></i>
<span>LinkedIn</span>
</Link>
<Link
href={`https://twitter.com/intent/tweet?url=${typeof window !== 'undefined' ? encodeURIComponent(window.location.href) : ''}&text=${encodeURIComponent(post.title)}`}
target="_blank"
rel="noopener noreferrer"
className="share-btn share-twitter"
aria-label="Share on Twitter"
>
<i className="fa-brands fa-twitter"></i>
<span>Twitter</span>
</Link>
<Link
href={`https://www.facebook.com/sharer/sharer.php?u=${typeof window !== 'undefined' ? encodeURIComponent(window.location.href) : ''}`}
target="_blank"
rel="noopener noreferrer"
className="share-btn share-facebook"
aria-label="Share on Facebook"
>
<i className="fa-brands fa-facebook-f"></i>
<span>Facebook</span>
</Link>
<button
onClick={() => {
if (typeof window !== 'undefined' && navigator.clipboard) {
navigator.clipboard.writeText(window.location.href);
alert('Link copied to clipboard!');
}
}}
className="share-btn share-copy"
aria-label="Copy link"
>
<i className="fa-solid fa-link"></i>
<span>Copy</span>
</button>
</div>
</div>
</div>
{/* Author Bio */}
{post.author && post.author.bio && (
<div className="author-bio-section">
<div className="author-bio-card">
<div className="author-avatar-container">
{post.author.avatar ? (
<Image
src={post.author.avatar}
alt={post.author.name}
width={90}
height={90}
className="rounded-circle"
/>
) : (
<div className="author-avatar-large">
<i className="fa-solid fa-user"></i>
</div>
)}
</div>
<div className="author-bio-content">
<div className="bio-label">About the Author</div>
<h6 className="author-name">{post.author.name}</h6>
<p className="author-bio-text">{post.author.bio}</p>
</div>
</div>
</div>
)}
{/* Navigation */}
<div className="article-navigation">
<Link href="/insights" className="btn-back-insights">
<i className="fa-solid fa-arrow-left me-2"></i>
Back to All Insights
</Link>
</div>
</footer>
</article>
</div>
</div>
</div>
</section>
);

View File

@@ -4,12 +4,30 @@ import Link from "next/link";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay } from "swiper/modules";
import "swiper/swiper-bundle.css";
import one from "@/public/images/blog/related-one.png";
import two from "@/public/images/blog/related-two.png";
import three from "@/public/images/blog/related-three.png";
import four from "@/public/images/blog/related-four.png";
import { useLatestPosts } from "@/lib/hooks/useBlog";
import { getValidImageUrl, getValidImageAlt, FALLBACK_IMAGES } from "@/lib/imageUtils";
const LatestPost = () => {
const { posts, loading, error } = useLatestPosts(8);
if (loading) {
return (
<section className="tp-latest-post pt-120 pb-120 bg-quinary">
<div className="container">
<div className="row">
<div className="col-12">
<p className="text-center">Loading latest posts...</p>
</div>
</div>
</div>
</section>
);
}
if (error || posts.length === 0) {
return null; // Don't show the section if there's an error or no posts
}
return (
<section className="tp-latest-post pt-120 pb-120 bg-quinary">
<div className="container">
@@ -17,14 +35,14 @@ const LatestPost = () => {
<div className="col-12 col-lg-7">
<div className="tp-lp-title text-center text-lg-start">
<h2 className="mt-8 fw-7 text-secondary title-anim">
Related posts
Related Insights
</h2>
</div>
</div>
<div className="col-12 col-lg-5">
<div className="tp-lp-cta text-center text-lg-end">
<Link href="blog" className="btn-line text-uppercase">
See All Posts
<Link href="/insights" className="btn-line text-uppercase">
View All Insights
</Link>
</div>
</div>
@@ -39,7 +57,7 @@ const LatestPost = () => {
slidesPerGroup={1}
freeMode={true}
speed={1200}
loop={true}
loop={posts.length > 3}
roundLengths={true}
modules={[Autoplay]}
autoplay={{
@@ -49,378 +67,43 @@ const LatestPost = () => {
}}
className="tp-lp-slider"
>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
{posts.map((post) => (
<SwiperSlide key={post.id}>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href={`/insights/${post.slug}`} className="w-100 overflow-hidden">
<Image
src={getValidImageUrl(post.thumbnail, FALLBACK_IMAGES.BLOG)}
width={400}
height={220}
className="w-100 mh-220"
alt={getValidImageAlt(post.title)}
/>
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
{post.author_name || 'Admin'}
</p>
<span></span>
<p className="date text-xs text-tertiary">
{new Date(post.published_at || post.created_at).toLocaleDateString('en-US', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href={`/insights/${post.slug}`}>
{post.title}
</Link>
</h5>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
</SwiperSlide>
))}
</Swiper>
</div>
</div>

View File

@@ -1,23 +1,54 @@
import { useState, useEffect } from "react";
import { BlogCategoryButtons } from "@/public/data/blog-category";
import { useBlogCategories } from "@/lib/hooks/useBlog";
const PostFilterButtons = ({ handleClick, active }: any) => {
const [categories, setCategories] = useState(BlogCategoryButtons);
const { categories: apiCategories, loading, error } = useBlogCategories();
const [categories, setCategories] = useState<any[]>([]);
// TODO: Replace with API call to get blog categories
// useEffect(() => {
// const fetchCategories = async () => {
// try {
// const response = await blogCategoryAPI.getAll();
// if (response.success) {
// setCategories(response.data);
// }
// } catch (error) {
// console.error('Error fetching categories:', error);
// }
// };
// fetchCategories();
// }, []);
useEffect(() => {
if (!loading && apiCategories.length > 0) {
// Add "All" category at the beginning
const allCategory = {
id: 0,
title: "All",
slug: "all",
display_order: 0
};
setCategories([allCategory, ...apiCategories]);
}
}, [apiCategories, loading]);
if (loading) {
return (
<div className="row">
<div className="col-12">
<div className="post-filter__wrapper mt-80">
<p>Loading categories...</p>
</div>
</div>
</div>
);
}
if (error) {
console.error('Error loading categories:', error);
// Fallback to showing "All" button only
return (
<div className="row">
<div className="col-12">
<div className="post-filter__wrapper mt-80">
<button
aria-label="Filter Post"
className="active"
onClick={() => handleClick("all")}
>
All
</button>
</div>
</div>
</div>
);
}
return (
<div className="row">

View File

@@ -5,102 +5,81 @@ import Link from "next/link";
import { AnimatePresence, motion } from "framer-motion";
import { getValidImageUrl, getValidImageAlt, FALLBACK_IMAGES } from "@/lib/imageUtils";
import PostFilterButtons from "./PostFilterButtons";
import { useBlogPosts } from "@/lib/hooks/useBlog";
const PostFilterItems = () => {
interface PostFilterItemsProps {
currentPage: number;
onPageChange: (page: number) => void;
onTotalPagesChange: (totalPages: number) => void;
postsPerPage?: number;
}
const PostFilterItems = ({ currentPage, onPageChange, onTotalPagesChange, postsPerPage = 10 }: PostFilterItemsProps) => {
const [active, setActive] = useState("all");
// Static blog posts data
const allPosts = [
{
id: 1,
title: "Enterprise Software Development Best Practices",
content: "Learn about the latest best practices in enterprise software development...",
slug: "enterprise-software-development-best-practices",
author_id: 1,
category_id: 1,
thumbnail: "/images/blog/one.png",
published: true,
category_title: "Development",
category_slug: "development",
author_name: "John Smith",
created_at: "2024-01-15T10:00:00Z",
updated_at: "2024-01-15T10:00:00Z"
},
{
id: 2,
title: "API Integration Strategies for Modern Enterprises",
content: "Discover effective strategies for API integration in enterprise environments...",
slug: "api-integration-strategies-modern-enterprises",
author_id: 1,
category_id: 2,
thumbnail: "/images/blog/two.png",
published: true,
category_title: "Integration",
category_slug: "integration",
author_name: "Jane Doe",
created_at: "2024-01-10T14:30:00Z",
updated_at: "2024-01-10T14:30:00Z"
},
{
id: 3,
title: "Cloud Migration: A Complete Guide",
content: "Everything you need to know about migrating your enterprise to the cloud...",
slug: "cloud-migration-complete-guide",
author_id: 1,
category_id: 3,
thumbnail: "/images/blog/three.png",
published: true,
category_title: "Cloud",
category_slug: "cloud",
author_name: "Mike Johnson",
created_at: "2024-01-05T09:15:00Z",
updated_at: "2024-01-05T09:15:00Z"
},
{
id: 4,
title: "Digital Transformation in Enterprise",
content: "How digital transformation is reshaping enterprise operations...",
slug: "digital-transformation-enterprise",
author_id: 1,
category_id: 1,
thumbnail: "/images/blog/four.png",
published: true,
category_title: "Development",
category_slug: "development",
author_name: "Sarah Wilson",
created_at: "2024-01-01T16:45:00Z",
updated_at: "2024-01-01T16:45:00Z"
const { posts: allPosts, loading, error, totalCount } = useBlogPosts({
category: active === "all" ? undefined : active,
page: currentPage,
page_size: postsPerPage
});
const [displayData, setDisplayData] = useState<any[]>([]);
useEffect(() => {
if (!loading && allPosts.length > 0) {
setDisplayData(allPosts);
}
];
const [displayData, setDisplayData] = useState(allPosts);
}, [allPosts, loading]);
// Calculate and update total pages when totalCount changes
useEffect(() => {
if (totalCount !== undefined && totalCount !== null) {
const calculatedTotalPages = Math.ceil(totalCount / postsPerPage);
onTotalPagesChange(calculatedTotalPages);
}
}, [totalCount, postsPerPage, onTotalPagesChange]);
const handleCategoryClick = (category: SetStateAction<string>) => {
if (category === active) return;
setActive(category);
setDisplayData([]);
onPageChange(1); // Reset to page 1 when category changes
if (category === "all") {
setDisplayData(allPosts);
return;
}
const filteredData = allPosts.filter(
(item) => item.category_slug === category
);
setTimeout(() => {
setDisplayData(filteredData);
}, 600);
// The API call will be triggered by the change in active state
// which will update allPosts and trigger the useEffect above
};
if (loading && displayData.length === 0) {
return (
<>
<PostFilterButtons active={active} handleClick={handleCategoryClick} />
<div className="row mt-60">
<div className="col-12">
<p className="text-center">Loading posts...</p>
</div>
</div>
</>
);
}
if (error) {
console.error('Error loading posts:', error);
return (
<>
<PostFilterButtons active={active} handleClick={handleCategoryClick} />
<div className="row mt-60">
<div className="col-12">
<p className="text-center text-danger">Error loading posts. Please try again later.</p>
</div>
</div>
</>
);
}
return (
<>
<PostFilterButtons active={active} handleClick={handleCategoryClick} />
<motion.div className="row mt-60 masonry-grid" layout>
<AnimatePresence>
{displayData.slice(0, 8).map((item) => {
{displayData.map((item) => {
return (
<motion.div
className="col-12 col-lg-6 grid-item-main"
@@ -114,7 +93,7 @@ const PostFilterItems = () => {
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link
href={`/blog/${item.slug}`}
href={`/insights/${item.slug}`}
className="w-100 overflow-hidden d-block"
>
<div className="parallax-image-wrap">
@@ -137,7 +116,7 @@ const PostFilterItems = () => {
</p>
<span></span>
<p className="date text-xs text-tertiary">
{new Date(item.created_at).toLocaleDateString('en-US', {
{new Date(item.published_at || item.created_at).toLocaleDateString('en-US', {
day: 'numeric',
month: 'short',
year: 'numeric'
@@ -145,7 +124,7 @@ const PostFilterItems = () => {
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href={`/blog/${item.slug}`}>{item.title}</Link>
<Link href={`/insights/${item.slug}`}>{item.title}</Link>
</h5>
</div>
</div>

View File

@@ -1,26 +1,37 @@
"use client";
import { useState } from "react";
import { useState, useEffect } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
import { useCaseStudies, useClients } from "@/lib/hooks/useCaseStudy";
import { getImageUrl } from "@/lib/imageUtils";
import one from "@/public/images/case/one.png";
import two from "@/public/images/case/two.png";
import three from "@/public/images/case/three.png";
import four from "@/public/images/case/four.png";
import five from "@/public/images/case/five.png";
import six from "@/public/images/case/six.png";
import seven from "@/public/images/case/seven.png";
import eight from "@/public/images/case/eight.png";
import thirteen from "@/public/images/case/thirteen.png";
import fourteen from "@/public/images/case/fourteen.png";
import fifteen from "@/public/images/case/fifteen.png";
import sixteen from "@/public/images/case/sixteen.png";
const CaseItems = () => {
const [activeTabIndex, setActiveTabIndex] = useState(0);
const { caseStudies, loading: casesLoading } = useCaseStudies();
const { clients, loading: clientsLoading } = useClients();
const handleTabClick = (index: number) => {
setActiveTabIndex(index);
};
// Filter case studies by category
const caseStudiesData = caseStudies.filter((cs) => !cs.client);
const clientCaseStudies = caseStudies.filter((cs) => cs.client);
if (casesLoading || clientsLoading) {
return (
<section className="fix-top pb-120 c-study">
<div className="container">
<div className="row">
<div className="col-12">
<p className="text-center">Loading case studies...</p>
</div>
</div>
</div>
</section>
);
}
return (
<section className="fix-top pb-120 c-study">
@@ -79,194 +90,38 @@ const CaseItems = () => {
}`}
>
<div className="row vertical-column-gap-lg">
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={two}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
3D Render
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
3D computer graphics, or 3D graphics.
{caseStudiesData.map((caseStudy) => (
<div key={caseStudy.id} className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href={`/case-study/${caseStudy.slug}`} className="w-100">
<Image
src={caseStudy.thumbnail ? getImageUrl(caseStudy.thumbnail) : one}
className="w-100 mh-300"
alt={caseStudy.title}
width={600}
height={400}
/>
</Link>
</h4>
</div>
<div className="content">
<Link href={`/case-study/${caseStudy.slug}`} className="mb-30 fw-6">
{caseStudy.category_name || 'Case Study'}
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href={`/case-study/${caseStudy.slug}`}>
{caseStudy.title}
</Link>
</h4>
</div>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={one}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
3D Render
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
Artificial intelligence is the simulation of human
processes.
</Link>
</h4>
</div>
))}
{caseStudiesData.length === 0 && (
<div className="col-12">
<p className="text-center">No case studies found.</p>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={three}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
UI / UX
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
User experience (UX) design is the process design
teams.
</Link>
</h4>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={four}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
Photography
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
Photography is the art, application, and practice.
</Link>
</h4>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={five}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
UI / UX
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
UX case study for a medical app- medical product
design.
</Link>
</h4>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={six}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
Icon Set
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
Make icon set for the educational project.
</Link>
</h4>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={seven}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
AI
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
User experience (UX) design is the process design
teams.
</Link>
</h4>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<Image
src={eight}
className="w-100 mh-300 "
alt="Image"
/>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
Road Map
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
UX site rode map app product design system
</Link>
</h4>
</div>
</div>
</div>
)}
</div>
</div>
<div
@@ -275,154 +130,48 @@ const CaseItems = () => {
}`}
>
<div className="row vertical-column-gap-lg">
<div className="col-12">
<div className="row vertical-column-gap-md align-items-center">
<div className="col-12 col-lg-6">
<div className="c-tab__client">
<h2 className="mt-8 fw-7 title-anim text-secondary mb-24">
Tarapio
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Pharetra sit
amet est tellus nibh sit lacus in duis. Condimentum
tellus sit pharetra consectetur magna massa. In odio
leo pellentesque aenean egestas est risus etiam.
Quam in nunc consectetur blandit id.
</p>
<div className="mt-40">
<Link
href="case-study-single"
className="btn-anim btn-anim-light"
>
Read More
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
{clientCaseStudies.map((caseStudy, index) => (
<div key={caseStudy.id} className="col-12">
<div className={`row vertical-column-gap-md align-items-center ${index % 2 === 1 ? 'flex-row-reverse' : ''}`}>
<div className="col-12 col-lg-6">
<div className="c-tab__client">
<h2 className="mt-8 fw-7 title-anim text-secondary mb-24">
{caseStudy.client?.name || caseStudy.title}
</h2>
<p className="cur-lg">
{caseStudy.excerpt || caseStudy.client?.description}
</p>
<div className="mt-40">
<Link
href={`/case-study/${caseStudy.slug}`}
className="btn-anim btn-anim-light"
>
Read More
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
</div>
</div>
</div>
</div>
<div className="col-12 col-lg-6 col-xxl-5 offset-xxl-1">
<div className="c-tab__thumb">
<Image
src={thirteen}
className="w-100 mh-300"
alt="Image"
/>
</div>
</div>
</div>
</div>
<div className="col-12">
<div className="row vertical-column-gap-md align-items-center">
<div className="col-12 col-lg-6 col-xxl-5">
<div className="c-tab__thumb">
<Image
src={fourteen}
className="w-100 mh-300"
alt="Image"
/>
</div>
</div>
<div className="col-12 col-lg-6 offset-xxl-1">
<div className="c-tab__client">
<h2 className="mt-8 fw-7 title-anim text-secondary mb-24">
Melenpo
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Pharetra sit
amet est tellus nibh sit lacus in duis. Condimentum
tellus sit pharetra consectetur magna massa. In odio
leo pellentesque aenean egestas est risus etiam.
Quam in nunc consectetur blandit id.
</p>
<div className="mt-40">
<Link
href="case-study-single"
className="btn-anim btn-anim-light"
>
Read More
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
<div className={`col-12 col-lg-6 col-xxl-5 ${index % 2 === 0 ? 'offset-xxl-1' : ''}`}>
<div className="c-tab__thumb">
<Image
src={caseStudy.thumbnail ? getImageUrl(caseStudy.thumbnail) : one}
className="w-100 mh-300"
alt={caseStudy.client?.name || caseStudy.title}
width={600}
height={400}
/>
</div>
</div>
</div>
</div>
</div>
<div className="col-12">
<div className="row vertical-column-gap-md align-items-center">
<div className="col-12 col-lg-6">
<div className="c-tab__client">
<h2 className="mt-8 fw-7 title-anim text-secondary mb-24">
Polax
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Pharetra sit
amet est tellus nibh sit lacus in duis. Condimentum
tellus sit pharetra consectetur magna massa. In odio
leo pellentesque aenean egestas est risus etiam.
Quam in nunc consectetur blandit id.
</p>
<div className="mt-40">
<Link
href="case-study-single"
className="btn-anim btn-anim-light"
>
Read More
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
</div>
</div>
</div>
<div className="col-12 col-lg-6 col-xxl-5 offset-xxl-1">
<div className="c-tab__thumb">
<Image
src={fifteen}
className="w-100 mh-300"
alt="Image"
/>
</div>
</div>
))}
{clientCaseStudies.length === 0 && (
<div className="col-12">
<p className="text-center">No client case studies found.</p>
</div>
</div>
<div className="col-12">
<div className="row vertical-column-gap-md align-items-center">
<div className="col-12 col-lg-6 col-xxl-5">
<div className="c-tab__thumb">
<Image
src={sixteen}
className="w-100 mh-300"
alt="Image"
/>
</div>
</div>
<div className="col-12 col-lg-6 offset-xxl-1">
<div className="c-tab__client">
<h2 className="mt-8 fw-7 title-anim text-secondary mb-24">
AINA
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Pharetra sit
amet est tellus nibh sit lacus in duis. Condimentum
tellus sit pharetra consectetur magna massa. In odio
leo pellentesque aenean egestas est risus etiam.
Quam in nunc consectetur blandit id.
</p>
<div className="mt-40">
<Link
href="case-study-single"
className="btn-anim btn-anim-light"
>
Read More
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>

View File

@@ -1,12 +1,47 @@
"use client";
import { use } from 'react';
import Image from "next/legacy/image";
import { useCaseStudy } from "@/lib/hooks/useCaseStudy";
import { getImageUrl } from "@/lib/imageUtils";
import poster from "@/public/images/case/poster.png";
import project from "@/public/images/case/project.png";
import nine from "@/public/images/case/nine.png";
import ten from "@/public/images/case/ten.png";
import eleven from "@/public/images/case/eleven.png";
import twelve from "@/public/images/case/twelve.png";
const CaseSingle = () => {
interface CaseSingleProps {
slug: string;
}
const CaseSingle = ({ slug }: CaseSingleProps) => {
const { caseStudy, loading, error } = useCaseStudy(slug);
if (loading) {
return (
<section className="c-details fix-top pb-120">
<div className="container">
<div className="row">
<div className="col-12">
<p className="text-center">Loading case study...</p>
</div>
</div>
</div>
</section>
);
}
if (error || !caseStudy) {
return (
<section className="c-details fix-top pb-120">
<div className="container">
<div className="row">
<div className="col-12">
<p className="text-center text-danger">Case study not found.</p>
</div>
</div>
</div>
</section>
);
}
return (
<section className="c-details fix-top pb-120">
<div className="container">
@@ -14,16 +49,20 @@ const CaseSingle = () => {
<div className="col-12">
<div className="c-details-intro">
<h2 className="mt-8 text-secondary title-anim fw-7">
Artificial intelligence is the simulation of human intelligence
processes.
{caseStudy.title}
</h2>
{caseStudy.subtitle && (
<h4 className="mt-4 text-secondary">{caseStudy.subtitle}</h4>
)}
<div className="poster mt-60 fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={poster}
src={caseStudy.poster_image ? getImageUrl(caseStudy.poster_image) : poster}
className="w-100 parallax-image mh-300"
alt="Image"
alt={caseStudy.title}
width={1200}
height={600}
/>
</div>
</div>
@@ -34,17 +73,14 @@ const CaseSingle = () => {
<h2 className="mt-8 fw-7 text-secondary title-anim mb-24">
Project
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Vestibulum
malesuada amet sagittis urna. Mattis eget ultricies est
morbi velit ultrices viverra elit facilisi. Amet est cras
euismod accumsan ornare sagittis ut integer. Sagittis sed
neque massa amet. Lorem vulputate nunc pulvinar maecenas
convallis augue. Magna massa viverra tincidunt vitae lacus
donec arcu consequat in. Maecenas dui nunc in convallis
vulputate vitae lectus eu lacus donec arcu consequat in.
Maecenas dui nunc in convallis vulputate vitae lectus eu.
</p>
{caseStudy.project_overview ? (
<p className="cur-lg">{caseStudy.project_overview}</p>
) : (
<div
className="cur-lg"
dangerouslySetInnerHTML={{ __html: caseStudy.description || '' }}
/>
)}
</div>
</div>
<div className="col-12 col-lg-6 col-xxl-5 offset-xxl-1 fade-wrapper">
@@ -52,88 +88,50 @@ const CaseSingle = () => {
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={project}
src={caseStudy.project_image ? getImageUrl(caseStudy.project_image) : project}
className="w-100 parallax-image mh-260"
alt="Image"
alt={`${caseStudy.title} - Project`}
width={600}
height={500}
/>
</div>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="road-map__content">
<h2 className="mt-8 fw-7 text-secondary title-anim mb-24">
Site Map
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Vestibulum
malesuada amet sagittis urna. Mattis eget ultricies est
morbi velit ultrices viverra elit facilisi. Amet est cras
euismod accumsan ornare sagittis ut integer. Sagittis sed
neque massa amet. Lorem vulputate nunc pulvinar maecenas
convallis augue. Magna massa viverra tincidunt vitae lacus
donec arcu consequat in. Maecenas dui nunc in convallis
vulputate vitae lectus eu.
</p>
</div>
</div>
</div>
<div className="row vertical-column-gap mt-60 fade-wrapper">
<div className="col-12 col-sm-6 col-xl-3">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={nine}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
{caseStudy.site_map_content && (
<div className="row">
<div className="col-12">
<div className="road-map__content">
<h2 className="mt-8 fw-7 text-secondary title-anim mb-24">
Site Map
</h2>
<p className="cur-lg">{caseStudy.site_map_content}</p>
</div>
</div>
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={ten}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
)}
{caseStudy.gallery_images && caseStudy.gallery_images.length > 0 && (
<div className="row vertical-column-gap mt-60 fade-wrapper">
{caseStudy.gallery_images.map((image) => (
<div key={image.id} className="col-12 col-sm-6 col-xl-3">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={getImageUrl(image.image) || nine}
className="w-100 mh-300 parallax-image"
alt={image.caption || caseStudy.title}
width={300}
height={300}
/>
</div>
</div>
</div>
</div>
</div>
))}
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={eleven}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</div>
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={twelve}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>

View File

@@ -1,4 +1,17 @@
const Process = () => {
"use client";
import { useCaseStudy } from "@/lib/hooks/useCaseStudy";
interface ProcessProps {
slug: string;
}
const Process = ({ slug }: ProcessProps) => {
const { caseStudy, loading } = useCaseStudy(slug);
if (loading || !caseStudy || !caseStudy.process_steps || caseStudy.process_steps.length === 0) {
return null;
}
return (
<section className="pt-120 pb-120 tp-process bg-black sticky-wrapper">
<div className="container">
@@ -6,64 +19,28 @@ const Process = () => {
<div className="col-12 col-lg-6">
<div className="process__content sticky-item">
<h2 className="mt-8 title-anim text-white fw-7 mb-24">
Artificial intelligence Process
{caseStudy.title} Process
</h2>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis. Pellentesque varius
lectus in massa placerat cursus. Donec in dictum nisl. In
maximus posuere leo nec porttitor.
{caseStudy.excerpt}
</p>
</div>
</div>
<div className="col-12 col-lg-6 col-xxl-5 offset-xxl-1">
<div className="process__thumb sticky-item">
<div className="process__single">
<span className="op-text text-white mb-40 cur-lg">01</span>
<h5 className="mt-8 text-white mb-24 title-anim">
Computer Vision
</h5>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis.
</p>
</div>
<div className="process__single">
<span className="op-text text-white mb-40 cur-lg">02</span>
<h5 className="mt-8 text-white mb-24 title-anim">
Computer Vision
</h5>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis.
</p>
</div>
<div className="process__single">
<span className="op-text text-white mb-40 cur-lg">03</span>
<h5 className="mt-8 text-white mb-24 title-anim">3D Vision</h5>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis.
</p>
</div>
<div className="process__single">
<span className="op-text text-white mb-40 cur-lg">04</span>
<h5 className="mt-8 text-white mb-24 title-anim">
Computer Vision
</h5>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis.
</p>
</div>
<div className="process__single">
<span className="op-text text-white mb-40 cur-lg">05</span>
<h5 className="mt-8 text-white mb-24 title-anim">3D Vision</h5>
<p className="cur-lg text-quinary">
Quisque varius malesuada dui, ut posuere purus gravida in.
Phasellus ultricies ullamcorper mollis.
</p>
</div>
{caseStudy.process_steps.map((step) => (
<div key={step.id} className="process__single">
<span className="op-text text-white mb-40 cur-lg">
{String(step.step_number).padStart(2, '0')}
</span>
<h5 className="mt-8 text-white mb-24 title-anim">
{step.title}
</h5>
<p className="cur-lg text-quinary">
{step.description}
</p>
</div>
))}
</div>
</div>
</div>

View File

@@ -1,9 +1,21 @@
"use client";
import Image from "next/legacy/image";
import Link from "next/link";
import { useCaseStudy } from "@/lib/hooks/useCaseStudy";
import { getImageUrl } from "@/lib/imageUtils";
import one from "@/public/images/case/one.png";
import two from "@/public/images/case/two.png";
const RelatedCase = () => {
interface RelatedCaseProps {
slug: string;
}
const RelatedCase = ({ slug }: RelatedCaseProps) => {
const { caseStudy, loading } = useCaseStudy(slug);
if (loading || !caseStudy || !caseStudy.related_case_studies || caseStudy.related_case_studies.length === 0) {
return null;
}
return (
<section className="pt-120 pb-120 c-study fade-wrapper">
<div className="container">
@@ -15,61 +27,37 @@ const RelatedCase = () => {
</div>
</div>
<div className="row vertical-column-gap-lg">
<div className="col-12 col-lg-6">
<div className="c-study-single fade-top">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={two}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
{caseStudy.related_case_studies.slice(0, 2).map((relatedCase) => (
<div key={relatedCase.id} className="col-12 col-lg-6">
<div className="c-study-single fade-top">
<div className="thumb mb-24">
<Link href={`/case-study/${relatedCase.slug}`} className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={relatedCase.thumbnail ? getImageUrl(relatedCase.thumbnail) : one}
className="w-100 mh-300 parallax-image"
alt={relatedCase.title}
width={600}
height={400}
/>
</div>
</div>
</div>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
3D Render
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
3D computer graphics, or 3D graphics.
</Link>
</h4>
</div>
<div className="content">
<Link href={`/case-study/${relatedCase.slug}`} className="mb-30 fw-6">
{relatedCase.category_name || 'Case Study'}
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href={`/case-study/${relatedCase.slug}`}>
{relatedCase.title}
</Link>
</h4>
</div>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="c-study-single fade-top">
<div className="thumb mb-24">
<Link href="case-study-single" className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={one}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</Link>
</div>
<div className="content">
<Link href="case-study" className="mb-30 fw-6">
3D Render
</Link>
<h4 className="fw-6 mt-8 text-secondary">
<Link href="case-study-single">
Artificial intelligence is the simulation of human
processes.
</Link>
</h4>
</div>
</div>
</div>
))}
</div>
</div>
</section>

View File

@@ -4,12 +4,12 @@ import Link from "next/link";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay } from "swiper/modules";
import "swiper/swiper-bundle.css";
import one from "@/public/images/blog/related-one.png";
import two from "@/public/images/blog/related-two.png";
import three from "@/public/images/blog/related-three.png";
import four from "@/public/images/blog/related-four.png";
import { useLatestPosts } from "@/lib/hooks/useBlog";
import { getValidImageUrl, getValidImageAlt, FALLBACK_IMAGES } from "@/lib/imageUtils";
const HomeLatestPost = () => {
const { posts, loading, error } = useLatestPosts(12); // Get 12 latest posts
return (
<section className="tp-latest-post pt-120 pb-120 bg-quinary">
<div className="container">
@@ -17,14 +17,14 @@ const HomeLatestPost = () => {
<div className="col-12 col-lg-7">
<div className="tp-lp-title text-center text-lg-start">
<h2 className="mt-8 fw-7 text-secondary title-anim">
Related posts
Latest Insights
</h2>
</div>
</div>
<div className="col-12 col-lg-5">
<div className="tp-lp-cta text-center text-lg-end">
<Link href="blog" className="btn-line text-uppercase">
See All Posts
<Link href="/insights" className="btn-line text-uppercase">
View All Insights
</Link>
</div>
</div>
@@ -32,397 +32,86 @@ const HomeLatestPost = () => {
<div className="row">
<div className="col-12">
<div className="tp-lp-slider-wrapper mt-60">
<div className="tp-lp-slider-wrapper">
<Swiper
slidesPerView={"auto"}
spaceBetween={24}
slidesPerGroup={1}
freeMode={true}
speed={1200}
loop={true}
roundLengths={true}
modules={[Autoplay]}
autoplay={{
delay: 5000,
disableOnInteraction: false,
pauseOnMouseEnter: true,
}}
className="tp-lp-slider"
>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
{loading ? (
<div className="text-center py-5">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="text-tertiary mt-3">Loading insights...</p>
</div>
) : error ? (
<div className="text-center py-5">
<p className="text-danger">Error loading insights. Please try again later.</p>
</div>
) : posts.length === 0 ? (
<div className="text-center py-5">
<p className="text-tertiary">No insights available yet.</p>
</div>
) : (
<div className="tp-lp-slider-wrapper">
<Swiper
slidesPerView={"auto"}
spaceBetween={24}
slidesPerGroup={1}
freeMode={true}
speed={1200}
loop={posts.length > 3}
roundLengths={true}
modules={[Autoplay]}
autoplay={{
delay: 5000,
disableOnInteraction: false,
pauseOnMouseEnter: true,
}}
className="tp-lp-slider"
>
{posts.map((post) => (
<SwiperSlide key={post.id}>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link
href={`/insights/${post.slug}`}
className="w-100 overflow-hidden d-block"
>
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={getValidImageUrl(post.thumbnail, FALLBACK_IMAGES.BLOG)}
width={400}
height={220}
className="w-100 mh-220 parallax-image"
alt={getValidImageAlt(post.title)}
/>
</div>
</div>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
{post.author_name || 'Admin'}
</p>
<span></span>
<p className="date text-xs text-tertiary">
{new Date(post.published_at || post.created_at).toLocaleDateString('en-US', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href={`/insights/${post.slug}`}>
{post.title}
</Link>
</h5>
</div>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={one}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={two}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={three}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link href="blog-single" className="w-100 overflow-hidden">
<Image
src={four}
width={400}
height={220}
className="w-100 mh-220"
alt="Image"
/>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
Denial Lio
</p>
<span></span>
<p className="date text-xs text-tertiary">
18 Dec 2022
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href="blog-single">
Tackling data of annotation problems in healthcare
</Link>
</h5>
</div>
</div>
</SwiperSlide>
</Swiper>
</div>
</SwiperSlide>
))}
</Swiper>
</div>
)}
</div>
</div>
</div>

View File

@@ -1,72 +1,92 @@
"use client";
import { useState, useEffect } from "react";
import { useState, useEffect, useMemo } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
import { getValidImageUrl, FALLBACK_IMAGES } from "@/lib/imageUtils";
import { useCaseStudies } from "@/lib/hooks/useCaseStudy";
import { API_CONFIG } from "@/lib/config/api";
const Story = () => {
const [activeIndex, setActiveIndex] = useState(0);
const [activeImageIndex, setActiveImageIndex] = useState(0);
// Static case studies data
const storyData = [
// Fetch case studies from API with ordering and limit
const params = useMemo(() => ({
ordering: 'display_order',
page_size: 5
}), []);
const { caseStudies, loading, error } = useCaseStudies(params);
// Fallback to static data if API fails or is loading
const staticStoryData = [
{
id: 1,
destination: "Financial Services",
category_name: "Financial Services",
title: "Banking System Modernization",
subtitle: "Complete digital transformation of legacy banking systems with enhanced security and real-time processing capabilities.",
image: "/images/case/one.png",
path: "/case-study/banking-system-modernization",
excerpt: "Complete digital transformation of legacy banking systems with enhanced security and real-time processing capabilities.",
thumbnail: "/images/case/one.png",
slug: "banking-system-modernization",
display_order: 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 2,
destination: "Healthcare",
category_name: "Healthcare",
title: "Patient Management System",
subtitle: "Enterprise-grade patient management system with HIPAA compliance and seamless integration across multiple healthcare facilities.",
image: "/images/case/two.png",
path: "/case-study/patient-management-system",
excerpt: "Enterprise-grade patient management system with HIPAA compliance and seamless integration across multiple healthcare facilities.",
thumbnail: "/images/case/two.png",
slug: "patient-management-system",
display_order: 2,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 3,
destination: "Manufacturing",
category_name: "Manufacturing",
title: "Supply Chain Optimization",
subtitle: "Advanced supply chain management system with real-time tracking, predictive analytics, and automated inventory management.",
image: "/images/case/three.png",
path: "/case-study/supply-chain-optimization",
excerpt: "Advanced supply chain management system with real-time tracking, predictive analytics, and automated inventory management.",
thumbnail: "/images/case/three.png",
slug: "supply-chain-optimization",
display_order: 3,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 4,
destination: "E-commerce",
category_name: "E-commerce",
title: "Multi-Platform Integration",
subtitle: "Seamless integration of multiple e-commerce platforms with unified inventory management and real-time synchronization.",
image: "/images/case/four.png",
path: "/case-study/multi-platform-integration",
excerpt: "Seamless integration of multiple e-commerce platforms with unified inventory management and real-time synchronization.",
thumbnail: "/images/case/four.png",
slug: "multi-platform-integration",
display_order: 4,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 5,
destination: "Education",
category_name: "Education",
title: "Learning Management System",
subtitle: "Comprehensive LMS with advanced analytics, automated grading, and seamless integration with existing educational tools.",
image: "/images/case/five.png",
path: "/case-study/learning-management-system",
excerpt: "Comprehensive LMS with advanced analytics, automated grading, and seamless integration with existing educational tools.",
thumbnail: "/images/case/five.png",
slug: "learning-management-system",
display_order: 5,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
];
// Use API data if available, otherwise use static data
const storyData = caseStudies.length > 0 ? caseStudies : staticStoryData;
// Log when API data is loaded
useEffect(() => {
if (caseStudies.length > 0) {
console.log('Case studies loaded from API:', caseStudies.length);
}
}, [caseStudies]);
const handleMouseEnter = (index: number) => {
setActiveIndex(index);
setActiveImageIndex(index);
@@ -93,12 +113,14 @@ const Story = () => {
onMouseEnter={() => handleMouseEnter(index)}
>
<p className="fw-6 mt-8">
<Link href={`${item.path}`}>{item.destination}</Link>
<Link href={`/case-study/${item.slug}`}>
{item.category_name || "Case Study"}
</Link>
</p>
<h5 className="fw-4 mt-12 mb-12 text-white">
{item.title}
</h5>
<p className="text-xs">{item.subtitle}</p>
<p className="text-xs">{item.excerpt}</p>
</div>
);
})}
@@ -108,6 +130,26 @@ const Story = () => {
<div className="col-12 col-lg-7 col-xxl-6 offset-xxl-1 d-none d-lg-block">
<div className="tp-story__thumbs sticky-item">
{storyData.map((item, index) => {
// Get the image URL - handle different scenarios
let imageUrl;
if (item.thumbnail) {
if (item.thumbnail.startsWith('http')) {
// Full URL (external)
imageUrl = item.thumbnail;
} else if (item.thumbnail.startsWith('/media')) {
// Relative path starting with /media
imageUrl = `${API_CONFIG.BASE_URL}${item.thumbnail}`;
} else {
// Just filename or relative path
imageUrl = `${API_CONFIG.MEDIA_URL}/${item.thumbnail}`;
}
console.log('Case study image URL:', item.title, '→', imageUrl);
} else {
// Fallback to static image
imageUrl = getValidImageUrl('/images/case/one.png', FALLBACK_IMAGES.CASE_STUDY);
console.log('Using fallback image for:', item.title);
}
return (
<div
key={index}
@@ -116,11 +158,11 @@ const Story = () => {
}`}
>
<Image
src={getValidImageUrl(item.image, FALLBACK_IMAGES.CASE_STUDY)}
src={imageUrl}
width={600}
height={300}
className="w-100 mh-300"
alt="Image"
alt={item.title || "Case Study"}
/>
</div>
);

View File

@@ -1,9 +1,6 @@
"use client";
import { useEffect } from "react";
import Link from "next/link";
import Image from "next/legacy/image";
import gsap from "gsap";
import ScrollTrigger from "gsap/dist/ScrollTrigger";
import location from "@/public/images/footer/location.png";
import phone from "@/public/images/footer/phone.png";
import gmail from "@/public/images/footer/gmail.png";
@@ -33,24 +30,6 @@ const Footer = () => {
})
};
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
gsap.set(".foot-fade", {
x: -100,
opacity: 0,
});
ScrollTrigger.batch(".foot-fade", {
start: "-100px bottom",
onEnter: (elements) =>
gsap.to(elements, {
x: 0,
opacity: 1,
stagger: 0.3,
}),
});
}, []);
// Get logo URL from static data
const logoSrc = headerData.logoUrl;
@@ -80,8 +59,8 @@ const Footer = () => {
width={160}
height={120}
style={{
height: 'auto',
maxHeight: '120px'
width: 'auto',
height: 'auto'
}}
/>
</Link>
@@ -132,7 +111,7 @@ const Footer = () => {
<div className="footer-section">
<h6 className="text-white fm fw-6 mb-24">Resources</h6>
<ul className="footer-links">
<li><Link href="blog">Software Blog</Link></li>
<li><Link href="/insights">Software Insights</Link></li>
<li><Link href="case-study">Development Resources</Link></li>
<li><Link href="services">API Documentation</Link></li>
<li><Link href="contact-us">Technical Support</Link></li>

View File

@@ -155,7 +155,9 @@ const Header = () => {
alt="Logo"
width={160}
height={120}
priority
style={{
width: 'auto',
height: 'auto'
}}
/>