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

@@ -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>
);