GNXSOFT.COM

This commit is contained in:
Iliyan Angelov
2025-09-26 00:15:37 +03:00
commit fe26b7cca4
16323 changed files with 2011881 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
"use client";
import { useState, useRef } from "react";
import Image from "next/image";
import { useServiceManagement } from "@/lib/hooks/useServices";
interface ServiceImageUploadProps {
serviceSlug: string;
currentImageUrl?: string;
onImageUploaded?: (service: any) => void;
}
const ServiceImageUpload: React.FC<ServiceImageUploadProps> = ({
serviceSlug,
currentImageUrl,
onImageUploaded,
}) => {
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [uploading, setUploading] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const { uploadServiceImage, loading, error } = useServiceManagement();
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
// Validate file type
if (!file.type.startsWith('image/')) {
alert('Please select an image file');
return;
}
// Validate file size (5MB limit)
if (file.size > 5 * 1024 * 1024) {
alert('File size must be less than 5MB');
return;
}
setSelectedFile(file);
// Create preview URL
const url = URL.createObjectURL(file);
setPreviewUrl(url);
}
};
const handleUpload = async () => {
if (!selectedFile) return;
try {
setUploading(true);
const updatedService = await uploadServiceImage(serviceSlug, selectedFile);
// Clean up preview URL
if (previewUrl) {
URL.revokeObjectURL(previewUrl);
}
setSelectedFile(null);
setPreviewUrl(null);
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
if (onImageUploaded) {
onImageUploaded(updatedService);
}
alert('Image uploaded successfully!');
} catch (err) {
console.error('Upload failed:', err);
alert('Failed to upload image. Please try again.');
} finally {
setUploading(false);
}
};
const handleCancel = () => {
setSelectedFile(null);
if (previewUrl) {
URL.revokeObjectURL(previewUrl);
setPreviewUrl(null);
}
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
};
return (
<div className="service-image-upload">
<div className="mb-3">
<label htmlFor="image-upload" className="form-label">
Service Image
</label>
<input
ref={fileInputRef}
type="file"
id="image-upload"
className="form-control"
accept="image/*"
onChange={handleFileSelect}
disabled={uploading || loading}
/>
<div className="form-text">
Select an image file (JPG, PNG, GIF). Maximum size: 5MB.
</div>
</div>
{/* Current Image */}
{currentImageUrl && !previewUrl && (
<div className="mb-3">
<label className="form-label">Current Image:</label>
<div className="current-image">
<Image
src={currentImageUrl}
alt="Current service image"
className="img-thumbnail"
width={200}
height={200}
style={{ maxWidth: '200px', maxHeight: '200px', objectFit: 'cover' }}
/>
</div>
</div>
)}
{/* Preview */}
{previewUrl && (
<div className="mb-3">
<label className="form-label">Preview:</label>
<div className="image-preview">
<Image
src={previewUrl}
alt="Preview"
className="img-thumbnail"
width={200}
height={200}
style={{ maxWidth: '200px', maxHeight: '200px', objectFit: 'cover' }}
/>
</div>
</div>
)}
{/* Error Display */}
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
{/* Action Buttons */}
{selectedFile && (
<div className="d-flex gap-2">
<button
type="button"
className="btn btn-primary"
onClick={handleUpload}
disabled={uploading || loading}
>
{uploading || loading ? (
<>
<span className="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
Uploading...
</>
) : (
'Upload Image'
)}
</button>
<button
type="button"
className="btn btn-secondary"
onClick={handleCancel}
disabled={uploading || loading}
>
Cancel
</button>
</div>
)}
</div>
);
};
export default ServiceImageUpload;

View File

@@ -0,0 +1,37 @@
"use client";
import { useEffect, useState } from "react";
import dynamic from "next/dynamic";
import "odometer/themes/odometer-theme-default.css";
import { useInView } from "react-intersection-observer";
const Odometer = dynamic(() => import("react-odometerjs"), {
ssr: false,
});
interface CounterProps {
value: number;
}
const Counter = ({ value }: CounterProps) => {
const [odometerValue, setOdometerValue] = useState(0);
const [ref, inView] = useInView();
useEffect(() => {
if (inView) {
setTimeout(() => {
setOdometerValue(value);
}, 1000);
}
}, [inView, value]);
return (
<span ref={ref}>
{inView ? (
<Odometer value={odometerValue} format="(,ddd)" theme="default" />
) : (
0
)}
</span>
);
};
export default Counter;

View File

@@ -0,0 +1,137 @@
'use client';
import { useState } from 'react';
export default function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: ''
});
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
// Simulate form submission
setTimeout(() => {
setSuccess(true);
setFormData({ name: '', email: '', subject: '', message: '' });
setLoading(false);
}, 2000);
};
if (success) {
return (
<div className="alert alert-success" role="alert">
<h4 className="alert-heading">Message Sent!</h4>
<p>Thank you for your message. We&apos;ll get back to you soon.</p>
<button
className="btn btn-outline-success"
onClick={() => setSuccess(false)}
>
Send Another Message
</button>
</div>
);
}
return (
<div className="container py-5">
<div className="row justify-content-center">
<div className="col-md-8">
<h2 className="text-center mb-4">Contact Us</h2>
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="row">
<div className="col-md-6 mb-3">
<label htmlFor="name" className="form-label">Name *</label>
<input
type="text"
className="form-control"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
</div>
<div className="col-md-6 mb-3">
<label htmlFor="email" className="form-label">Email *</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
</div>
<div className="mb-3">
<label htmlFor="subject" className="form-label">Subject</label>
<input
type="text"
className="form-control"
id="subject"
name="subject"
value={formData.subject}
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label htmlFor="message" className="form-label">Message *</label>
<textarea
className="form-control"
id="message"
name="message"
rows={5}
value={formData.message}
onChange={handleChange}
required
></textarea>
</div>
<div className="text-center">
<button
type="submit"
className="btn btn-primary btn-lg"
disabled={loading}
>
{loading ? (
<>
<span className="spinner-border spinner-border-sm me-2" role="status"></span>
Sending...
</>
) : (
'Send Message'
)}
</button>
</div>
</form>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,89 @@
'use client';
import { useState, useEffect } from 'react';
export default function ServicesList() {
// Static services data
const services = [
{
id: 1,
title: "Web Development",
description: "Custom web applications built with modern technologies",
slug: "web-development",
icon: "code",
price: 2500,
featured: true,
display_order: 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 2,
title: "Mobile Apps",
description: "Native and cross-platform mobile applications",
slug: "mobile-apps",
icon: "phone",
price: 3500,
featured: false,
display_order: 2,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
];
const handleDeleteService = (id: number) => {
if (!confirm('Are you sure you want to delete this service?')) {
return;
}
// Note: This is a demo - in a real app, you'd handle deletion differently
console.log('Service deletion requested for ID:', id);
};
return (
<div className="container py-5">
<div className="row">
<div className="col-12">
<h2 className="mb-4">Our Services</h2>
<div className="row">
{services.map((service) => (
<div key={service.id} className="col-md-6 col-lg-4 mb-4">
<div className="card h-100">
<div className="card-body">
<div className="d-flex justify-content-between align-items-start mb-3">
<h5 className="card-title">{service.title}</h5>
{service.featured && (
<span className="badge bg-primary">Featured</span>
)}
</div>
<p className="card-text">{service.description}</p>
{service.price && (
<p className="text-muted">
<strong>Starting at: ${service.price}</strong>
</p>
)}
<div className="mt-auto">
<a
href={`/services/${service.slug}`}
className="btn btn-primary me-2"
>
Learn More
</a>
<button
className="btn btn-outline-danger btn-sm"
onClick={() => handleDeleteService(service.id)}
>
Delete
</button>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,271 @@
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { useAbout } from "@/lib/hooks/useAbout";
const AboutBanner = () => {
const { data, loading, error } = useAbout();
const [currentMetric, setCurrentMetric] = useState(0);
useEffect(() => {
// Auto-rotate metrics
const interval = setInterval(() => {
setCurrentMetric(prev => (prev + 1) % 3);
}, 4000);
return () => clearInterval(interval);
}, []);
// Show loading state
if (loading) {
return (
<section className="about-banner fix-top pb-120 position-relative overflow-x-clip">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="mt-3">Loading about us content...</p>
</div>
</div>
</div>
</div>
</section>
);
}
// Show error state
if (error) {
return (
<section className="about-banner fix-top pb-120 position-relative overflow-x-clip">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="alert alert-danger" role="alert">
<h4 className="alert-heading">Error Loading Content</h4>
<p>{error}</p>
<hr />
<p className="mb-0">Please try refreshing the page or contact support if the problem persists.</p>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
// Use API data or fallback to default content
const bannerData = data?.banner;
const metrics = [
{ value: "500+", label: "Fortune 500 Clients", icon: "fa-building", color: "#3b82f6" },
{ value: "99.9%", label: "Uptime Guarantee", icon: "fa-shield-halved", color: "#10b981" },
{ value: "24/7", label: "Enterprise Support", icon: "fa-headset", color: "#f59e0b" },
{ value: "15+", label: "Years Experience", icon: "fa-award", color: "#8b5cf6" }
];
return (
<section className="hero-banner">
{/* Video-like Background */}
<div className="hero-background">
{/* Animated Code Lines */}
<div className="code-animation">
<div className="code-line line-1">
<span className="code-keyword">const</span> enterprise = <span className="code-string">'mission-critical'</span>;
</div>
<div className="code-line line-2">
<span className="code-keyword">if</span> (security.level === <span className="code-string">'enterprise'</span>) &#123;
</div>
<div className="code-line line-3">
&nbsp;&nbsp;deploy<span className="code-function">()</span>;
</div>
<div className="code-line line-4">
&#125;
</div>
</div>
{/* Floating Tech Icons */}
<div className="floating-tech">
<div className="tech-icon icon-1">
<i className="fa-solid fa-shield-halved"></i>
</div>
<div className="tech-icon icon-2">
<i className="fa-solid fa-cloud"></i>
</div>
<div className="tech-icon icon-3">
<i className="fa-solid fa-server"></i>
</div>
<div className="tech-icon icon-4">
<i className="fa-solid fa-lock"></i>
</div>
<div className="tech-icon icon-5">
<i className="fa-solid fa-chart-line"></i>
</div>
<div className="tech-icon icon-6">
<i className="fa-solid fa-database"></i>
</div>
</div>
{/* Enterprise Dashboard Elements */}
<div className="dashboard-elements">
<div className="dashboard-card card-1">
<div className="card-header">
<i className="fa-solid fa-shield-check"></i>
<span>Security Status</span>
</div>
<div className="card-content">
<div className="status-indicator resolved"></div>
<span>Enterprise Grade</span>
</div>
</div>
<div className="dashboard-card card-2">
<div className="card-header">
<i className="fa-solid fa-clock"></i>
<span>SLA Response</span>
</div>
<div className="card-content">
<div className="metric-value">99.9%</div>
<span>Uptime</span>
</div>
</div>
<div className="dashboard-card card-3">
<div className="card-header">
<i className="fa-solid fa-building"></i>
<span>Enterprise Clients</span>
</div>
<div className="card-content">
<div className="metric-value">500+</div>
<span>Fortune 500</span>
</div>
</div>
</div>
{/* Network Connection Lines */}
<div className="network-lines">
<div className="connection-line line-1"></div>
<div className="connection-line line-2"></div>
<div className="connection-line line-3"></div>
<div className="connection-line line-4"></div>
</div>
{/* Data Flow Particles */}
<div className="data-particles">
<div className="particle particle-1"></div>
<div className="particle particle-2"></div>
<div className="particle particle-3"></div>
<div className="particle particle-4"></div>
<div className="particle particle-5"></div>
<div className="particle particle-6"></div>
</div>
{/* Background Gradient Overlay */}
<div className="video-overlay"></div>
</div>
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-lg-10 col-xl-8">
<div className="hero-content text-center">
{/* Badge */}
<div className="hero-badge">
<div className="badge-icon">
<i className="fa-solid fa-shield-check"></i>
</div>
<span>Enterprise Security Certified</span>
</div>
{/* Main Title */}
<h1 className="hero-title">
{bannerData?.title || "Mission-Critical Software Solutions for Global Enterprises"}
</h1>
{/* Description */}
<p className="hero-description">
{bannerData?.description || "Trusted by Fortune 500 companies worldwide, we deliver enterprise-grade software solutions with 99.9% uptime SLA, SOC 2 Type II certification, and 24/7 dedicated support. Our mission-critical platforms power digital transformation across industries."}
</p>
{/* Key Metrics */}
<div className="hero-metrics">
{metrics.map((metric, index) => (
<div
key={index}
className={`metric-item ${currentMetric === index ? 'active' : ''}`}
onClick={() => setCurrentMetric(index)}
>
<div className="metric-icon" style={{ backgroundColor: metric.color }}>
<i className={`fa-solid ${metric.icon}`}></i>
</div>
<div className="metric-content">
<div className="metric-value">{metric.value}</div>
<div className="metric-label">{metric.label}</div>
</div>
</div>
))}
</div>
{/* CTA Buttons */}
<div className="hero-actions">
<Link href={bannerData?.cta_link || "services"} className="btn-primary">
<span>View Enterprise Solutions</span>
<i className="fa-solid fa-arrow-right"></i>
</Link>
<Link href="contact-us" className="btn-secondary">
<span>Schedule Consultation</span>
<i className="fa-solid fa-calendar-check"></i>
</Link>
</div>
{/* Trust Badges */}
<div className="trust-badges">
<div className="trust-badge">
<i className="fa-solid fa-shield-check"></i>
<span>SOC 2 Type II</span>
</div>
<div className="trust-badge">
<i className="fa-solid fa-lock"></i>
<span>ISO 27001</span>
</div>
<div className="trust-badge">
<i className="fa-solid fa-certificate"></i>
<span>GDPR Compliant</span>
</div>
<div className="trust-badge">
<i className="fa-solid fa-globe"></i>
<span>Global Operations</span>
</div>
<div className="trust-badge">
<i className="fa-solid fa-award"></i>
<span>Microsoft Partner</span>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Social Links */}
<div className="social-links">
<Link href="https://www.linkedin.com/company/enterprisesoft-solutions" target="_blank" className="social-link">
<i className="fa-brands fa-linkedin-in"></i>
</Link>
<Link href="https://github.com/enterprisesoft" target="_blank" className="social-link">
<i className="fa-brands fa-github"></i>
</Link>
<Link href="https://www.twitter.com/enterprisesoft" target="_blank" className="social-link">
<i className="fa-brands fa-twitter"></i>
</Link>
<Link href="https://stackoverflow.com/teams/enterprisesoft" target="_blank" className="social-link">
<i className="fa-brands fa-stack-overflow"></i>
</Link>
</div>
</section>
);
};
export default AboutBanner;

View File

@@ -0,0 +1,367 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Navigation } from "swiper/modules";
import "swiper/swiper-bundle.css";
import Counter from "../../common/Counter";
import one from "@/public/images/study/one.png";
import two from "@/public/images/study/two.png";
import three from "@/public/images/study/three.png";
import four from "@/public/images/study/four.png";
import five from "@/public/images/study/five.png";
const AboutCase = () => {
return (
<section className="tp-study pt-120 pb-120 bg-quinary">
<div className="container">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-lg-7">
<div className="tp-lp-title text-center text-lg-start">
<div className="enterprise-badge mb-20">
<span className="badge enterprise-badge-content">
<i className="fa-solid fa-chart-line"></i>
Success Stories
</span>
</div>
<h2 className="mt-8 fw-7 text-secondary title-anim">
Enterprise Success Stories
</h2>
<p className="cur-lg mt-20">
Discover how we&apos;ve helped Fortune 500 companies and innovative startups
achieve their digital transformation goals through cutting-edge technology solutions.
</p>
</div>
</div>
<div className="col-12 col-lg-5">
<div className="tp-study-arrows d-flex justify-content-center justify-content-lg-end">
<button className="prev-study" aria-label="previous study">
<span className="material-symbols-outlined">west</span>
</button>
<button className="next-study" aria-label="next study">
<span className="material-symbols-outlined">east</span>
</button>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="tp-study-slider-wrapper">
<div className="tp-study-slider-wrap">
<Swiper
slidesPerView={"auto"}
spaceBetween={24}
slidesPerGroup={1}
freeMode={true}
speed={1200}
loop={true}
roundLengths={true}
modules={[Autoplay, Navigation]}
autoplay={{
delay: 5000,
disableOnInteraction: false,
pauseOnMouseEnter: true,
}}
className="tp-study-slider"
navigation={{
nextEl: ".prev-study",
prevEl: ".next-study",
}}
>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={one}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={two}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={three}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={four}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={five}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={one}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={two}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={three}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={four}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="tp-study-slider__single">
<div className="thumb">
<Link href="case-study-single">
<Image
src={five}
className="w-100 mh-400"
alt="Image"
width={400}
height={400}
/>
</Link>
</div>
<div className="content text-center">
<h5 className="mt-8 mb-12 text-white fw-5 text-uppercase">
<Link href="case-study-single">ENTERPRISE CRM</Link>
</h5>
<Link href="case-study-single" className="btn-angle">
View
<span></span>
</Link>
</div>
</div>
</SwiperSlide>
</Swiper>
</div>
</div>
</div>
</div>
<div className="row pt-120 vertical-column-gap-lg">
<div className="col-12 col-sm-6 col-xl-3">
<div className="counter__single text-center">
<h2 className="fw-5 text-secondary mt-8 mb-16">
<span className="odometer">
<Counter value={500} />
</span>
<span>+</span>
</h2>
<p className="text-tertiary">Enterprise Projects</p>
</div>
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="counter__single text-center">
<h2 className="fw-5 text-secondary mt-8 mb-16">
<span className="odometer">
<Counter value={99} />
</span>
<span>.9%</span>
</h2>
<p className="text-tertiary">Uptime SLA</p>
</div>
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="counter__single text-center">
<h2 className="fw-5 text-secondary mt-8 mb-16">
<span className="odometer">
<Counter value={15} />
</span>
<span>+</span>
</h2>
<p className="text-tertiary">Years Experience</p>
</div>
</div>
<div className="col-12 col-sm-6 col-xl-3">
<div className="counter__single text-center border-0">
<h2 className="fw-5 text-secondary mt-8 mb-16">
<span className="odometer">
<Counter value={200} />
</span>
<span>+</span>
</h2>
<p className="text-tertiary">Expert Engineers</p>
</div>
</div>
</div>
</div>
</section>
);
};
export default AboutCase;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const AboutInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default AboutInitAnimations;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const AboutScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default AboutScrollProgressButton;

View File

@@ -0,0 +1,264 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { useAbout } from "@/lib/hooks/useAbout";
import { AboutService as AboutServiceType, AboutProcess } from "@/lib/api/aboutService";
import thumb from "@/public/images/service/two.png";
import thumbTwo from "@/public/images/service/three.png";
const AboutServiceComponent = () => {
const { data, loading, error } = useAbout();
// Show loading state
if (loading) {
return (
<section className="tp-service pt-120 pb-120">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="mt-3">Loading service content...</p>
</div>
</div>
</div>
</div>
</section>
);
}
// Show error state
if (error) {
return (
<section className="tp-service pt-120 pb-120">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="alert alert-danger" role="alert">
<h4 className="alert-heading">Error Loading Content</h4>
<p>{error}</p>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
// Use API data or fallback to default content
const serviceData = data?.service as AboutServiceType | undefined;
const processData = data?.process as AboutProcess | undefined;
return (
<section className="tp-service">
<div className="container">
<div className="row align-items-center">
<div className="col-12 col-lg-5">
<div className="tp-service__thumb">
<Link href="service-single" className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={serviceData?.image_url || thumb}
className="w-100 parallax-image"
alt="Enterprise Technology Solutions"
width={400}
height={300}
/>
</div>
</div>
</Link>
</div>
</div>
<div className="col-12 col-lg-7 col-xl-6 offset-xl-1">
<div className="tp-service__content">
<div className="enterprise-badge">
<i className={serviceData?.badge_icon || "fa-solid fa-users"}></i>
{serviceData?.badge_text || "About Our Company"}
</div>
<h2 className="title-anim">
{serviceData?.title || "Enterprise Technology Leaders"}
</h2>
<p>
{serviceData?.description || "Founded in 2008, EnterpriseSoft Solutions has emerged as a premier enterprise software company, serving Fortune 500 companies and innovative startups worldwide. Our team of 200+ engineers, architects, and consultants specializes in delivering mission-critical software solutions that drive digital transformation and business growth."}
</p>
<div className="enterprise-features">
<div className="row">
{serviceData?.features && serviceData.features.length > 0 ? (
serviceData.features.map((feature, index) => (
<div key={index} className="col-12 col-md-6">
<div className="feature-item">
<div className="feature-icon">
<i className={feature.icon}></i>
</div>
<div className="feature-content">
<h6>{feature.title}</h6>
<p>{feature.description}</p>
</div>
</div>
</div>
))
) : (
<>
<div className="col-12 col-md-6">
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-shield-halved"></i>
</div>
<div className="feature-content">
<h6>Enterprise Security</h6>
<p>SOC 2 Type II Certified</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-cloud"></i>
</div>
<div className="feature-content">
<h6>Cloud Native</h6>
<p>AWS, Azure, GCP Partners</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-certificate"></i>
</div>
<div className="feature-content">
<h6>Certified Experts</h6>
<p>Microsoft, AWS, Google Certified</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-globe"></i>
</div>
<div className="feature-content">
<h6>Global Reach</h6>
<p>Offices in 5 Countries</p>
</div>
</div>
</div>
</>
)}
</div>
</div>
<div className="mt-4">
<Link href={serviceData?.cta_link || "service-single"} className="btn-line">
{serviceData?.cta_text || "Explore Our Solutions"}
</Link>
</div>
</div>
</div>
</div>
<div className="row align-items-center">
<div className="col-12 col-lg-6">
<div className="tp-service__content">
<div className="enterprise-badge">
<i className={processData?.badge_icon || "fa-solid fa-cogs"}></i>
{processData?.badge_text || "Our Methodology"}
</div>
<h2 className="title-anim">
{processData?.title || "Enterprise Development Process"}
</h2>
<p>
{processData?.description || "Our proven enterprise development methodology combines agile practices with enterprise-grade security, scalability, and compliance requirements. We follow industry best practices including DevOps, CI/CD, and microservices architecture to deliver robust, scalable solutions."}
</p>
<div className="process-steps">
<div className="row">
{processData?.steps && processData.steps.length > 0 ? (
processData.steps.map((step, index) => (
<div key={index} className="col-12 col-md-6">
<div className="process-step">
<div className="step-number">{step.step_number}</div>
<div className="step-content">
<h6>{step.title}</h6>
<p>{step.description}</p>
</div>
</div>
</div>
))
) : (
<>
<div className="col-12 col-md-6">
<div className="process-step">
<div className="step-number">01</div>
<div className="step-content">
<h6>Discovery & Planning</h6>
<p>Comprehensive analysis and architecture design</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="process-step">
<div className="step-number">02</div>
<div className="step-content">
<h6>Development & Testing</h6>
<p>Agile development with continuous testing</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="process-step">
<div className="step-number">03</div>
<div className="step-content">
<h6>Deployment & Integration</h6>
<p>Seamless deployment and system integration</p>
</div>
</div>
</div>
<div className="col-12 col-md-6">
<div className="process-step">
<div className="step-number">04</div>
<div className="step-content">
<h6>Support & Maintenance</h6>
<p>24/7 enterprise support and maintenance</p>
</div>
</div>
</div>
</>
)}
</div>
</div>
<div className="mt-4">
<Link href={processData?.cta_link || "service-single"} className="btn-line">
{processData?.cta_text || "View Our Services"}
</Link>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="tp-service__thumb">
<Link href="service-single" className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={processData?.image_url || thumbTwo}
className="w-100 parallax-image"
alt="Enterprise Development Process"
width={400}
height={300}
/>
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
);
};
export default AboutServiceComponent;

View File

@@ -0,0 +1,151 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { useAbout } from "@/lib/hooks/useAbout";
import { AboutJourney } from "@/lib/api/aboutService";
import thumb from "@/public/images/start-thumb.png";
const AboutStarter = () => {
const { data, loading, error } = useAbout();
// Show loading state
if (loading) {
return (
<section className="tp-gallery pt-120 bg-black position-relative overflow-x-clip">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="spinner-border text-light" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="mt-3 text-white">Loading journey content...</p>
</div>
</div>
</div>
</div>
</section>
);
}
// Show error state
if (error) {
return (
<section className="tp-gallery pt-120 bg-black position-relative overflow-x-clip">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center py-5">
<div className="alert alert-danger" role="alert">
<h4 className="alert-heading">Error Loading Content</h4>
<p>{error}</p>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
// Use API data or fallback to default content
const journeyData = data?.journey as AboutJourney | undefined;
return (
<section className="tp-gallery">
<div className="container">
<div className="row align-items-center">
<div className="col-12 col-lg-6">
<div className="tp-gallery__content">
<div className="enterprise-badge">
<i className={journeyData?.badge_icon || "fa-solid fa-rocket"}></i>
{journeyData?.badge_text || "Our Journey"}
</div>
<h2 className="title-anim">
{journeyData?.title || "From Startup to Enterprise Leader"}
</h2>
<p>
{journeyData?.description || "Founded in 2008 by three visionary engineers, Itify Technologies began as a small startup with a big dream: to revolutionize how enterprises approach software development. What started as a passion project has grown into a global enterprise software company serving Fortune 500 clients worldwide."}
</p>
<div className="journey-milestones">
{journeyData?.milestones && journeyData.milestones.length > 0 ? (
journeyData.milestones.map((milestone, index) => (
<div key={index} className="milestone-item">
<div className="milestone-year">
<span className="year-badge">{milestone.year}</span>
</div>
<div className="milestone-content">
<h6>{milestone.title}</h6>
<p>{milestone.description}</p>
</div>
</div>
))
) : (
<>
<div className="milestone-item">
<div className="milestone-year">
<span className="year-badge">2008</span>
</div>
<div className="milestone-content">
<h6>Company Founded</h6>
<p>Started with 3 engineers</p>
</div>
</div>
<div className="milestone-item">
<div className="milestone-year">
<span className="year-badge">2015</span>
</div>
<div className="milestone-content">
<h6>Enterprise Focus</h6>
<p>Pivoted to enterprise solutions</p>
</div>
</div>
<div className="milestone-item">
<div className="milestone-year">
<span className="year-badge">2020</span>
</div>
<div className="milestone-content">
<h6>Global Expansion</h6>
<p>Opened offices in 5 countries</p>
</div>
</div>
</>
)}
</div>
<div className="mt-4">
<Link
href={journeyData?.cta_link || "services"}
className="btn-line"
>
{journeyData?.cta_text || "Explore Solutions"}
</Link>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="tp-gallery__thumb">
<Image
src={journeyData?.image_url || thumb}
className="w-100"
alt="Enterprise Journey"
width={500}
height={400}
style={{
objectFit: 'contain',
borderRadius: '12px',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.1)',
maxWidth: '100%',
maxHeight: '500px',
width: '100%',
height: 'auto'
}}
/>
</div>
</div>
</div>
</div>
</section>
);
};
export default AboutStarter;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const BlogInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default BlogInitAnimations;

View File

@@ -0,0 +1,68 @@
import Link from "next/link";
import PostFilterItems from "./post-filter/PostFilterItems";
const BlogItems = () => {
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>
</div>
<div className="col-12 col-lg-5">
<form action="#" method="post" autoComplete="off">
<div className="search-form">
<input
type="search"
name="search-post"
id="searchPost"
placeholder="Search"
required
/>
<button
type="submit"
aria-label="search post"
title="search post"
>
<i className="fa-solid fa-magnifying-glass"></i>
</button>
</div>
</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>
</div>
</div>
</div>
</div>
</section>
);
};
export default BlogItems;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const BlogScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default BlogScrollProgressButton;

View File

@@ -0,0 +1,210 @@
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";
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>
</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>
</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>
</div>
</div>
</div>
</div>
</section>
);
};
export default BlogSingle;

View File

@@ -0,0 +1,434 @@
"use client";
import Image from "next/legacy/image";
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";
const LatestPost = () => {
return (
<section className="tp-latest-post pt-120 pb-120 bg-quinary">
<div className="container">
<div className="row vertical-column-gap align-items-center">
<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
</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>
</div>
</div>
</div>
<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>
</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>
</div>
</div>
</div>
</div>
</section>
);
};
export default LatestPost;

View File

@@ -0,0 +1,44 @@
import { useState, useEffect } from "react";
import { BlogCategoryButtons } from "@/public/data/blog-category";
const PostFilterButtons = ({ handleClick, active }: any) => {
const [categories, setCategories] = useState(BlogCategoryButtons);
// 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();
// }, []);
return (
<div className="row">
<div className="col-12">
<div className="post-filter__wrapper mt-80">
{categories.map((item) => {
return (
<button
aria-label="Filter Post"
key={item.id}
className={active === item.slug ? " active" : ""}
onClick={() => handleClick(item.slug)}
>
{item.title}
</button>
);
})}
</div>
</div>
</div>
);
};
export default PostFilterButtons;

View File

@@ -0,0 +1,161 @@
"use client";
import { useState, SetStateAction, useEffect } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
import { AnimatePresence, motion } from "framer-motion";
import { getValidImageUrl, getValidImageAlt, FALLBACK_IMAGES } from "@/lib/imageUtils";
import PostFilterButtons from "./PostFilterButtons";
const PostFilterItems = () => {
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 [displayData, setDisplayData] = useState(allPosts);
const handleCategoryClick = (category: SetStateAction<string>) => {
if (category === active) return;
setActive(category);
setDisplayData([]);
if (category === "all") {
setDisplayData(allPosts);
return;
}
const filteredData = allPosts.filter(
(item) => item.category_slug === category
);
setTimeout(() => {
setDisplayData(filteredData);
}, 600);
};
return (
<>
<PostFilterButtons active={active} handleClick={handleCategoryClick} />
<motion.div className="row mt-60 masonry-grid" layout>
<AnimatePresence>
{displayData.slice(0, 8).map((item) => {
return (
<motion.div
className="col-12 col-lg-6 grid-item-main"
key={item.id}
layout
initial={{ opacity: 0, scale: 0.6 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.6 }}
transition={{ duration: 0.6 }}
>
<div className="tp-lp-slider__single topy-tilt">
<div className="thumb mb-24">
<Link
href={`/blog/${item.slug}`}
className="w-100 overflow-hidden d-block"
>
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={getValidImageUrl(item.thumbnail, FALLBACK_IMAGES.BLOG)}
className="w-100 mh-220 parallax-image"
alt={getValidImageAlt(item.title)}
width={400}
height={220}
/>
</div>
</div>
</Link>
</div>
<div className="content">
<div className="tp-lp-post__meta mb-24 mt-8">
<p className="author text-xs text-tertiary">
{item.author_name || 'Admin'}
</p>
<span></span>
<p className="date text-xs text-tertiary">
{new Date(item.created_at).toLocaleDateString('en-US', {
day: 'numeric',
month: 'short',
year: 'numeric'
})}
</p>
</div>
<h5 className="mt-8 fw-5 text-secondary">
<Link href={`/blog/${item.slug}`}>{item.title}</Link>
</h5>
</div>
</div>
</motion.div>
);
})}
</AnimatePresence>
</motion.div>
</>
);
};
export default PostFilterItems;

View File

@@ -0,0 +1,110 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Image from "next/legacy/image";
import Link from "next/link";
import thumb from "@/public/images/banner/cp-thumb.png";
const CareerBanner = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
if (document.querySelector(".career-banner")) {
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".career-banner",
start: "center center",
end: "+=100%",
scrub: true,
pin: false,
},
});
tl.to(".cp-banner-thumb", {
opacity: 0.1,
y: "40%",
duration: 2,
});
tl.to(
".career-banner",
{
"--scale": 3,
duration: 2,
},
0
);
}
}, []);
return (
<section className="career-banner fix-top bg-black position-relative overflow-hidden">
<div className="container">
<div className="row justify-content-end">
<div className="col-12 col-lg-11">
<div className="row align-items-center">
<div className="col-12 col-sm-11 col-md-10 col-xl-8 col-xxl-9">
<div className="cp-banner__content">
<h2 className="mt-8 fw-7 text-xxl title-anim text-white">
Grow your career the way you feel
</h2>
</div>
</div>
<div className="col-12 col-sm-1 col-md-2 col-xl-4 col-xxl-3">
<div className="cp-banner-thumb dir-rtl">
<Image src={thumb} className="mh-300 unset" alt="Image" width={400} height={300} />
</div>
</div>
</div>
</div>
</div>
</div>
<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>
<Link href="#scroll-to" className="scroll-to">
Scroll
<span className="arrow"></span>
</Link>
<span className="sm-c"></span>
<span className="sm-c sm-cl"></span>
</section>
);
};
export default CareerBanner;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const CareerInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default CareerInitAnimations;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const CareerScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default CareerScrollProgressButton;

View File

@@ -0,0 +1,153 @@
import Link from "next/link";
const JobSingle = () => {
return (
<section className="job-single fix-top pb-120 sticky-wrapper">
<div className="container">
<div className="row vertical-column-gap">
<div className="col-12 col-lg-7">
<div className="j-d-content sticky-item">
<div className="intro">
<h2 className="mt-8 text-secondary fw-7 title-anim mb-24">
UI/UX Design
</h2>
<p>
Position: <span className="position mb-12">(02)</span>
</p>
<p>
Location: <span className="location">(Remote)</span>
</p>
</div>
<div className="group pt-120">
<h4 className="mt-8 text-secondary title-anim fw-6 mb-24">
Who we are
</h4>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Augue morbi sapien
malesuada augue massa vivamus pharetra. Pellentesque velit
lectus dui convallis posuere viverra enim mauris. Pulvinar
quam vitae ut viverra. Vitae quis cursus magna sit amet neque
ultricies lectus massa. Sem mauris tincidunt risus enim
adipiscing viverra. Interdum lectus interdum diam ultricies
molestie. In et ullamcorper semper odio enim.
</p>
</div>
<div className="group mt-60">
<h4 className="mt-8 text-secondary title-anim fw-6 mb-24">
What you want
</h4>
<ul>
<li>
you have at least three years of commercial experience
</li>
<li>
you have a strong web/UI portfolio including published
projects
</li>
<li>fluent English in verbal and written communication</li>
<li>
you are passionate about user interface and web design
</li>
<li>issues are challenges not show-stoppers for you</li>
<li>you are a trend seeker</li>
<li>you bring a lot of attention to details</li>
<li>
you plan upfront, think ahead, and are ready to be surprised
</li>
<li>you think about the full picture</li>
<li>
you are familiar with any UI design tool, i.e., Sketch,
Figma or Adobe XD
</li>
</ul>
</div>
<div className="group mt-60">
<h4 className="mt-8 text-secondary title-anim fw-6 mb-24">
Who we are
</h4>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Augue morbi sapien
malesuada augue massa vivamus pharetra. Pellentesque velit
lectus dui convallis posuere viverra enim mauris. Pulvinar
quam vitae ut viverra. Vitae quis cursus magna sit amet neque
ultricies lectus massa. Sem mauris tincidunt risus enim
adipiscing viverra. Interdum lectus interdum diam ultricies
molestie. In et ullamcorper semper odio enim.
</p>
</div>
<div className="group mt-60">
<h4 className="mt-8 text-secondary title-anim fw-6 mb-24">
Bonus points
</h4>
<ul>
<li>you have at least three years</li>
<li>you have a strong web/UI portfolio including</li>
<li>fluent English in verbal</li>
<li>you are passionate about user interface</li>
<li>issues are challenges</li>
<li>you are a seeker</li>
</ul>
</div>
<div className="group mt-60">
<h4 className="mt-8 text-secondary title-anim fw-6 mb-24">
What you get is what you see
</h4>
<ul>
<li>you have at least three years</li>
<li>you have a strong web/UI portfolio including</li>
<li>fluent English in verbal</li>
<li>you are passionate about user interface</li>
<li>issues are challenges</li>
<li>you are a seeker</li>
<li>fluent English in verbal and written communication</li>
<li>
you are passionate about user interface and web design
</li>
<li>issues are challenges not show-stoppers for you</li>
<li>you are a trend seeker</li>
<li>you bring a lot of attention to details</li>
<li>
you plan upfront, think ahead, and are ready to be surprised
</li>
</ul>
</div>
</div>
</div>
<div className="col-12 col-lg-5 col-xxl-4 offset-xxl-1">
<div className="j-d-sidebar sticky-item">
<div className="intro">
<span className="text-uppercase mt-8 text-tertiary mb-16">
JOIN US
</span>
<h4 className="mt-8 fw-5 title-anim text-secondary mb-16">
UI/UX Design
</h4>
<p>Full-time (40hr per week)</p>
</div>
<div className="content mt-40">
<p className="mt-8 fw-5 text-xl text-secondary mb-16">
Salary-
</p>
<p className="mt-8 fw-5 text-xl text-secondary mb-16">
$1500-$2000 per month
</p>
<p className="mt-8 fw-4 text-tertiary mb-30">
+ VAT (B2B) + bonuses
</p>
<p className="mt-8 fw-4 text-tertiary mb-16">Remote / Poznań</p>
<p className="mt-8 fw-4 text-tertiary">Start: ASAP</p>
</div>
<div className="cta mt-60">
<Link href="/" className="btn">
Apply Now
</Link>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default JobSingle;

View File

@@ -0,0 +1,56 @@
import Image from "next/legacy/image";
import one from "@/public/images/masonry/one.png";
import two from "@/public/images/masonry/two.png";
import three from "@/public/images/masonry/three.png";
import four from "@/public/images/masonry/four.png";
import five from "@/public/images/masonry/five.png";
import six from "@/public/images/masonry/six.png";
import seven from "@/public/images/masonry/seven.png";
const MasonryGallery = () => {
return (
<div className="mason pt-120 pb-120 fade-wrapper">
<div className="container">
<div className="row vertical-column-gap">
<div className="col-12 col-md-3">
<div className="mason-single fade-top">
<Image src={one} className="mh-260" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-4">
<div className="mason-single fade-bottom">
<Image src={two} className="mh-260" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-3">
<div className="mason-single fade-left">
<Image src={three} className="mh-260 botter" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-2">
<div className="mason-single fade-right">
<Image src={seven} className="mh-260 botter" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-5">
<div className="mason-single fade-top">
<Image src={five} className="mh-260" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-2">
<div className="mason-single fade-bottom">
<Image src={six} className="mh-260" alt="Image" width={300} height={260} />
</div>
</div>
<div className="col-12 col-md-5">
<div className="mason-single toper fade-right">
<Image src={four} className="mh-260" alt="Image" width={300} height={260} />
</div>
</div>
</div>
</div>
</div>
);
};
export default MasonryGallery;

View File

@@ -0,0 +1,205 @@
import Link from "next/link";
const OpenPosition = () => {
return (
<section className="op-position pt-120 pb-120" id="scroll-to">
<div className="container">
<div className="row">
<div className="col-12">
<div className="intro mb-60">
<h2 className="mt-8 fw-7 title-anim text-secondary">
Open Positions
</h2>
</div>
</div>
<div className="col-12 mt-60">
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">01</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">UI/UX Design</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(04 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">02</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Administrative Assistant</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(03 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">03</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Software Engineer</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(12 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">04</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Data Entry Clerk</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(01 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">05</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Marketing Manager</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(09 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">06</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Executive Assistant</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(07 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
<div className="op-position-single appear-down">
<div className="row vertical-column-gap align-items-center">
<div className="col-12 col-sm-2">
<span className="fw-7 text-xl text-tertiary">07</span>
</div>
<div className="col-12 col-sm-5">
<h4 className="fw-7">
<Link href="job-single">Lead Product Designer</Link>
</h4>
</div>
<div className="col-12 col-sm-3">
<div className="roles">
<span className="text-tertiary fw-5 text-xl">
(03 Open Roles)
</span>
</div>
</div>
<div className="col-12 col-sm-2">
<div className="cta text-start text-sm-end">
<Link href="job-single">
<span className="material-symbols-outlined">east</span>
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default OpenPosition;

View File

@@ -0,0 +1,85 @@
import Image from "next/legacy/image";
import time from "@/public/images/time.png";
import trans from "@/public/images/trans.png";
import support from "@/public/images/support.png";
import skill from "@/public/images/skill.png";
const Thrive = () => {
return (
<section className="thrive pt-120 pb-120 bg-black fade-wrapper">
<div className="container">
<div className="row">
<div className="col-12">
<div className="intro">
<h2 className="mt-8 fw-7 title-anim text-white">
What lets us thrive together
</h2>
</div>
</div>
</div>
<div className="row vertical-column-gap-lg mt-60">
<div className="col-12 col-md-6 fade-top">
<div className="thumb">
<Image src={time} alt="Image" width={80} height={80} />
</div>
<div className="content mt-40">
<h4 className="mt-8 title-anim fw-7 text-white mb-16">
Flexible workday
</h4>
<p className="cur-lg text-quinary">
Lorem ipsum dolor sit amet consectetur. Elit sit laoreet aliquam
porttitor mattis vel feugiat eget. Nunc nunc nunc urna lorem.
mattis vel feugiat eget.
</p>
</div>
</div>
<div className="col-12 col-md-6 fade-top">
<div className="thumb">
<Image src={trans} alt="Image" width={80} height={80} />
</div>
<div className="content mt-40">
<h4 className="mt-8 title-anim fw-7 text-white mb-16">
Transparency
</h4>
<p className="cur-lg text-quinary">
Lorem ipsum dolor sit amet consectetur. Elit sit laoreet aliquam
porttitor mattis vel feugiat eget. Nunc nunc nunc urna lorem.
mattis vel feugiat eget.
</p>
</div>
</div>
<div className="col-12 col-md-6 fade-top">
<div className="thumb">
<Image src={support} alt="Image" width={80} height={80} />
</div>
<div className="content mt-40">
<h4 className="mt-8 title-anim fw-7 text-white mb-16">Support</h4>
<p className="cur-lg text-quinary">
Lorem ipsum dolor sit amet consectetur. Elit sit laoreet aliquam
porttitor mattis vel feugiat eget. Nunc nunc nunc urna lorem.
mattis vel feugiat eget.
</p>
</div>
</div>
<div className="col-12 col-md-6 fade-top">
<div className="thumb">
<Image src={skill} alt="Image" width={80} height={80} />
</div>
<div className="content mt-40">
<h4 className="mt-8 title-anim fw-7 text-white mb-16">
Growth Skill
</h4>
<p className="cur-lg text-quinary">
Lorem ipsum dolor sit amet consectetur. Elit sit laoreet aliquam
porttitor mattis vel feugiat eget. Nunc nunc nunc urna lorem.
mattis vel feugiat eget.
</p>
</div>
</div>
</div>
</div>
</section>
);
};
export default Thrive;

View File

@@ -0,0 +1,436 @@
"use client";
import { useState } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
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 handleTabClick = (index: number) => {
setActiveTabIndex(index);
};
return (
<section className="fix-top pb-120 c-study">
<div className="container">
<div className="row">
<div className="col-12">
<div className="c-study-banner pb-120">
<div className="row">
<div className="col-12 col-lg-9">
<h2 className="mt-8 title-anim fw-7 text-secondary mb-24">
Case Studies
</h2>
<p className="cur-lg">
Lorem ipsum dolor sit amet consectetur. Morbi in non nibh
netus tortor. Non vitae ut consectetur sit quam egestas
praesent. Enim augue cras donec sed pellentesque tortor
maecenas. Tellus duis sit justo neque. Est elit diam quam
venenatis sit morbi sed dignissim eros.
</p>
</div>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="c-study-inner pt-120 mb-60">
<div className="c-study-btns">
<button
className={`study-btn ${
activeTabIndex === 0 ? "study-btn-active" : ""
}`}
onClick={() => handleTabClick(0)}
>
Case Study
</button>
<span></span>
<button
className={`study-btn ${
activeTabIndex === 1 ? "study-btn-active" : ""
}`}
onClick={() => handleTabClick(1)}
>
Client
</button>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="c-content-wrapper mt-60">
<div
className={`c-tab-single ${
activeTabIndex === 0 ? "active-tab" : ""
}`}
>
<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.
</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={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>
</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
className={`c-tab-single ${
activeTabIndex === 1 ? "active-tab" : ""
}`}
>
<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>
</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>
</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>
</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>
</div>
</div>
</div>
</section>
);
};
export default CaseItems;

View File

@@ -0,0 +1,145 @@
import Image from "next/legacy/image";
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 = () => {
return (
<section className="c-details fix-top pb-120">
<div className="container">
<div className="row">
<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.
</h2>
<div className="poster mt-60 fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={poster}
className="w-100 parallax-image mh-300"
alt="Image"
/>
</div>
</div>
</div>
<div className="row vertical-column-gap align-items-center pt-120 pb-120">
<div className="col-12 col-lg-6">
<div className="c-details-content">
<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>
</div>
</div>
<div className="col-12 col-lg-6 col-xxl-5 offset-xxl-1 fade-wrapper">
<div className="c-details-thumb fade-top">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={project}
className="w-100 parallax-image mh-260"
alt="Image"
/>
</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>
</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"
/>
</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>
</div>
</section>
);
};
export default CaseSingle;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const CaseStudyInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default CaseStudyInitAnimations;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const CaseStudyScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default CaseStudyScrollProgressButton;

View File

@@ -0,0 +1,75 @@
const Process = () => {
return (
<section className="pt-120 pb-120 tp-process bg-black sticky-wrapper">
<div className="container">
<div className="row vertical-column-gap">
<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
</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.
</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>
</div>
</div>
</div>
</div>
</section>
);
};
export default Process;

View File

@@ -0,0 +1,79 @@
import Image from "next/legacy/image";
import Link from "next/link";
import one from "@/public/images/case/one.png";
import two from "@/public/images/case/two.png";
const RelatedCase = () => {
return (
<section className="pt-120 pb-120 c-study fade-wrapper">
<div className="container">
<div className="row">
<div className="col-12 col-lg-9">
<h2 className="mt-8 title-anim fw-7 text-secondary mb-24">
Similar Case Studies
</h2>
</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"
/>
</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>
</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>
);
};
export default RelatedCase;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const ContactInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default ContactInitAnimations;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const ContactScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default ContactScrollProgressButton;

View File

@@ -0,0 +1,603 @@
"use client";
import { usePathname } from "next/navigation";
import { useState } from "react";
import Image from "next/legacy/image";
import thumb from "@/public/images/contact-thumb.png";
import { contactApiService, ContactFormData } from "@/lib/api/contactService";
const ContactSection = () => {
const pathname = usePathname();
const isServiceSingle = pathname === "/service-single" || pathname === "/about-us";
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
email: '',
phone: '',
company: '',
jobTitle: '',
industry: '',
companySize: '',
budget: '',
timeline: '',
projectType: '',
message: '',
newsletter: false,
privacy: false
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<{
type: 'success' | 'error' | null;
message: string;
}>({ type: null, message: '' });
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { name, value, type } = e.target;
if (type === 'checkbox') {
const checked = (e.target as HTMLInputElement).checked;
setFormData(prev => ({ ...prev, [name]: checked }));
} else {
setFormData(prev => ({ ...prev, [name]: value }));
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setSubmitStatus({ type: null, message: '' });
try {
// Transform form data to match API requirements
const apiData: ContactFormData = {
first_name: formData.firstName,
last_name: formData.lastName,
email: formData.email,
phone: formData.phone || undefined,
company: formData.company,
job_title: formData.jobTitle,
industry: formData.industry || undefined,
company_size: formData.companySize || undefined,
project_type: formData.projectType || undefined,
timeline: formData.timeline || undefined,
budget: formData.budget || undefined,
message: formData.message,
newsletter_subscription: formData.newsletter,
privacy_consent: formData.privacy
};
// Submit to Django API
const response = await contactApiService.submitContactForm(apiData);
setSubmitStatus({
type: 'success',
message: response.message || 'Thank you! We\'ll contact you within 24 hours.'
});
// Reset form on success
setFormData({
firstName: '',
lastName: '',
email: '',
phone: '',
company: '',
jobTitle: '',
industry: '',
companySize: '',
budget: '',
timeline: '',
projectType: '',
message: '',
newsletter: false,
privacy: false
});
} catch (error) {
console.error('Contact form submission error:', error);
setSubmitStatus({
type: 'error',
message: error instanceof Error ? error.message : 'Failed to submit form. Please try again.'
});
} finally {
setIsSubmitting(false);
}
};
return (
<section
className={
"tp-contact pb-120 fade-wrapper" +
(isServiceSingle ? " pt-120" : " fix-top")
}
>
<div className="container">
{/* Contact Information Cards */}
<div className="row mb-40">
<div className="col-12 col-md-4">
<div className="contact-info-card">
<div className="contact-info-icon">
<i className="fa-solid fa-phone"></i>
</div>
<h4>Phone Support</h4>
<p>Main Contact & Emergency</p>
<a href="tel:+359897338147">+359 897 338 147</a>
<a href="tel:+359896138030">Emergency: +359 896 13 80 30</a>
<span className="contact-hours">Available 24/7</span>
</div>
</div>
<div className="col-12 col-md-4">
<div className="contact-info-card">
<div className="contact-info-icon">
<i className="fa-solid fa-envelope"></i>
</div>
<h4>Email Support</h4>
<p>Software Solutions</p>
<a href="mailto:info@gnxsoft.com">info@gnxsoft.com</a>
<a href="mailto:contact@gnxsoft.com">contact@gnxsoft.com</a>
<span className="contact-hours">24/7 Response Time</span>
</div>
</div>
<div className="col-12 col-md-4">
<div className="contact-info-card">
<div className="contact-info-icon">
<i className="fa-solid fa-map-marker-alt"></i>
</div>
<h4>Office Locations</h4>
<p>Our Location</p>
<address>
GNX Soft Ltd.<br />
Tsar Simeon I, 56<br />
Burgas, Burgas 8000, Bulgaria
</address>
<span className="contact-hours">Schedule a Visit</span>
</div>
</div>
</div>
<div className="row vertical-column-gap-md justify-content-between mt-40">
<div className="col-12 col-lg-7">
<div className="tp-contact__content">
<div className="contact-form mt-40">
<form onSubmit={handleSubmit} className="enterprise-form">
<div className="form-section">
<h4 className="form-section-title">
<i className="fa-solid fa-user"></i>
Personal Information
</h4>
<div className="row">
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="firstName">First Name *</label>
<input
type="text"
name="firstName"
id="firstName"
value={formData.firstName}
onChange={handleInputChange}
placeholder="John"
required
/>
</div>
</div>
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="lastName">Last Name *</label>
<input
type="text"
name="lastName"
id="lastName"
value={formData.lastName}
onChange={handleInputChange}
placeholder="Smith"
required
/>
</div>
</div>
</div>
<div className="row">
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="email">Business Email *</label>
<input
type="email"
name="email"
id="email"
value={formData.email}
onChange={handleInputChange}
placeholder="john.smith@company.com"
required
/>
</div>
</div>
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="phone">Phone Number</label>
<input
type="tel"
name="phone"
id="phone"
value={formData.phone}
onChange={handleInputChange}
placeholder="+1 (555) 123-4567"
/>
</div>
</div>
</div>
</div>
<div className="form-section">
<h4 className="form-section-title">
<i className="fa-solid fa-building"></i>
Company Information
</h4>
<div className="row">
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="company">Company Name *</label>
<input
type="text"
name="company"
id="company"
value={formData.company}
onChange={handleInputChange}
placeholder="Acme Corporation"
required
/>
</div>
</div>
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="jobTitle">Job Title *</label>
<input
type="text"
name="jobTitle"
id="jobTitle"
value={formData.jobTitle}
onChange={handleInputChange}
placeholder="CTO, IT Director, etc."
required
/>
</div>
</div>
</div>
<div className="row">
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="industry">Industry</label>
<select
name="industry"
id="industry"
value={formData.industry}
onChange={handleInputChange}
>
<option value="">Select Industry</option>
<option value="technology">Technology</option>
<option value="finance">Finance</option>
<option value="healthcare">Healthcare</option>
<option value="manufacturing">Manufacturing</option>
<option value="retail">Retail</option>
<option value="education">Education</option>
<option value="government">Government</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="companySize">Company Size</label>
<select
name="companySize"
id="companySize"
value={formData.companySize}
onChange={handleInputChange}
>
<option value="">Select Company Size</option>
<option value="1-10">1-10 employees</option>
<option value="11-50">11-50 employees</option>
<option value="51-200">51-200 employees</option>
<option value="201-1000">201-1000 employees</option>
<option value="1000+">1000+ employees</option>
</select>
</div>
</div>
</div>
</div>
<div className="form-section">
<h4 className="form-section-title">
<i className="fa-solid fa-project-diagram"></i>
Project Details
</h4>
<div className="row">
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="projectType">Project Type</label>
<select
name="projectType"
id="projectType"
value={formData.projectType}
onChange={handleInputChange}
>
<option value="">Select Project Type</option>
<option value="software-development">Software Development</option>
<option value="cloud-migration">Cloud Migration</option>
<option value="digital-transformation">Digital Transformation</option>
<option value="data-analytics">Data Analytics</option>
<option value="security-compliance">Security & Compliance</option>
<option value="integration">System Integration</option>
<option value="consulting">Consulting Services</option>
</select>
</div>
</div>
<div className="col-12 col-md-6">
<div className="input-single">
<label htmlFor="timeline">Project Timeline</label>
<select
name="timeline"
id="timeline"
value={formData.timeline}
onChange={handleInputChange}
>
<option value="">Select Timeline</option>
<option value="immediate">Immediate (0-3 months)</option>
<option value="short">Short-term (3-6 months)</option>
<option value="medium">Medium-term (6-12 months)</option>
<option value="long">Long-term (12+ months)</option>
<option value="planning">Still planning</option>
</select>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="input-single">
<label htmlFor="budget">Project Budget Range</label>
<select
name="budget"
id="budget"
value={formData.budget}
onChange={handleInputChange}
>
<option value="">Select Budget Range</option>
<option value="under-50k">Under 50,000</option>
<option value="50k-100k">50,000 - 100,000</option>
<option value="100k-250k">100,000 - 250,000</option>
<option value="250k-500k">250,000 - 500,000</option>
<option value="500k-1m">500,000 - 1,000,000</option>
<option value="over-1m">Over 1,000,000</option>
<option value="discuss">Prefer to discuss</option>
</select>
</div>
</div>
</div>
<div className="input-single">
<label htmlFor="message">Project Description *</label>
<textarea
name="message"
id="message"
value={formData.message}
onChange={handleInputChange}
placeholder="Please describe your project requirements, current challenges, and expected outcomes..."
rows={5}
required
/>
</div>
</div>
<div className="form-section">
<h4 className="form-section-title">
<i className="fa-solid fa-shield-halved"></i>
Privacy & Communication
</h4>
<div className="checkbox-group">
<div className="checkbox-single">
<input
type="checkbox"
name="newsletter"
id="newsletter"
checked={formData.newsletter}
onChange={handleInputChange}
/>
<label htmlFor="newsletter">
Subscribe to our newsletter for industry insights and product updates
</label>
</div>
<div className="checkbox-single">
<input
type="checkbox"
name="privacy"
id="privacy"
checked={formData.privacy}
onChange={handleInputChange}
required
/>
<label htmlFor="privacy">
I agree to the <a href="/privacy-policy">Privacy Policy</a> and consent to being contacted by our team *
</label>
</div>
</div>
</div>
{/* Status Message */}
{submitStatus.type && (
<div className={`form-status mt-30 ${submitStatus.type === 'success' ? 'success' : 'error'}`}>
<div className="status-content">
<i className={`fa-solid ${submitStatus.type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'}`}></i>
<span>{submitStatus.message}</span>
{submitStatus.type === 'error' && (
<div className="error-details mt-10">
<small>
If the problem persists, please contact us directly at{' '}
<a href="mailto:info@gnxsoft.com" className="text-primary">info@gnxsoft.com</a>
</small>
</div>
)}
</div>
</div>
)}
<div className="form-actions mt-40">
<button
type="submit"
className="btn btn-primary enterprise-btn"
disabled={isSubmitting}
>
{isSubmitting ? (
<>
<span>Sending...</span>
<i className="fa-solid fa-spinner fa-spin"></i>
</>
) : (
<>
<span>Request Software Consultation</span>
<i className="fa-solid fa-arrow-right"></i>
</>
)}
</button>
<p className="form-disclaimer">
<i className="fa-solid fa-lock"></i>
Your information is secure and will only be used to provide you with relevant software solutions.
</p>
</div>
</form>
</div>
</div>
</div>
<div className="col-12 col-lg-5">
<div className="tp-contact__sidebar">
<div className="contact-sidebar-card">
<div className="sidebar-header">
<h3>Why Choose Our Software Solutions?</h3>
<div className="enterprise-badge">
<i className="fa-solid fa-award"></i>
<span>Enterprise Grade</span>
</div>
</div>
<div className="sidebar-features">
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-shield-halved"></i>
</div>
<div className="feature-content">
<h4>Incident Management</h4>
<p>Advanced incident management software with real-time monitoring and automated response capabilities.</p>
<div className="feature-tags">
<span className="tag">Real-time</span>
<span className="tag">Automated</span>
</div>
</div>
</div>
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-users"></i>
</div>
<div className="feature-content">
<h4>Custom Development</h4>
<p>Tailored software solutions built to your exact specifications with dedicated development teams.</p>
<div className="feature-tags">
<span className="tag">Dedicated Teams</span>
<span className="tag">Custom</span>
</div>
</div>
</div>
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-chart-line"></i>
</div>
<div className="feature-content">
<h4>System Integrations & APIs</h4>
<p>Seamless integration with your existing systems and third-party applications through robust APIs for unified workflows.</p>
<div className="feature-tags">
<span className="tag">API-First</span>
<span className="tag">Seamless</span>
</div>
</div>
</div>
<div className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-cogs"></i>
</div>
<div className="feature-content">
<h4>Data Replication</h4>
<p>Reliable data replication and synchronization solutions to ensure data consistency across systems.</p>
<div className="feature-tags">
<span className="tag">Reliable</span>
<span className="tag">Sync</span>
</div>
</div>
</div>
</div>
</div>
<div className="contact-sidebar-card">
<h3>Next Steps</h3>
<div className="next-steps">
<div className="step-item">
<div className="step-number">1</div>
<div className="step-content">
<h4>Initial Consultation</h4>
<p>We&apos;ll review your requirements and provide initial recommendations within 24 hours.</p>
</div>
</div>
<div className="step-item">
<div className="step-number">2</div>
<div className="step-content">
<h4>Custom Demo</h4>
<p>Schedule a personalized demonstration tailored to your specific use case.</p>
</div>
</div>
<div className="step-item">
<div className="step-number">3</div>
<div className="step-content">
<h4>Proposal & Pricing</h4>
<p>Receive a detailed proposal with custom pricing and implementation timeline.</p>
</div>
</div>
</div>
</div>
<div className="contact-sidebar-card">
<h3>Find Us</h3>
<div className="company-map">
<div className="map-container">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2933.123456789!2d27.4758968970689!3d42.496781103070504!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x40a6b8c9d1234567%3A0x1234567890abcdef!2sBurgas%2C%20Bulgaria!5e0!3m2!1sen!2sbg!4v1234567890123!5m2!1sen!2sbg"
width="100%"
height="200"
style={{ border: 0, borderRadius: '8px' }}
allowFullScreen
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
title="Company Location"
/>
</div>
<div className="map-info">
<div className="location-details">
<div className="location-icon">
<i className="fa-solid fa-map-marker-alt"></i>
</div>
<div className="location-text">
<h4>GNX Soft Ltd.</h4>
<p>Tsar Simeon I, 56<br />Burgas, Burgas 8000, Bulgaria</p>
</div>
</div>
<div className="location-actions">
<a href="https://maps.google.com/?q=Tsar+Simeon+I+56+Burgas+Bulgaria" target="_blank" rel="noopener noreferrer" className="map-link">
<i className="fa-solid fa-directions"></i>
Get Directions
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default ContactSection;

View File

@@ -0,0 +1,395 @@
"use client";
import Link from "next/link";
import { useState, useEffect } from "react";
const HomeBanner = () => {
const [currentTextIndex, setCurrentTextIndex] = useState(0);
const [isTransitioning, setIsTransitioning] = useState(false);
// Static banner slides data
const carouselTexts = [
{
id: 1,
badge: "Enterprise Solutions",
icon: "fa-solid fa-shield-halved",
heading: "Secure Enterprise Software",
highlight: "Development",
subheading: "for Modern Businesses",
description: "We build enterprise-grade software solutions with advanced security, scalability, and 24/7 support. Transform your business with our custom development services.",
button_text: "Explore Solutions",
button_url: "/services",
is_active: true,
display_order: 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 2,
badge: "API Integration",
icon: "fa-solid fa-plug",
heading: "Seamless API",
highlight: "Integration",
subheading: "& System Connectivity",
description: "Connect all your systems with our robust API development and integration services. Enable smooth data flow and unified workflows across your organization.",
button_text: "Learn More",
button_url: "/services/api-development",
is_active: true,
display_order: 2,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 3,
badge: "Cloud Migration",
icon: "fa-solid fa-cloud",
heading: "Cloud-First",
highlight: "Solutions",
subheading: "for Enterprise Scale",
description: "Migrate to the cloud with confidence. Our cloud solutions provide improved scalability, security, and cost-effectiveness for your enterprise operations.",
button_text: "Start Migration",
button_url: "/services/cloud-solutions",
is_active: true,
display_order: 3,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
];
// Carousel rotation effect
useEffect(() => {
if (carouselTexts.length <= 1) return;
const interval = setInterval(() => {
setIsTransitioning(true);
setTimeout(() => {
setCurrentTextIndex((prevIndex) =>
prevIndex === carouselTexts.length - 1 ? 0 : prevIndex + 1
);
setIsTransitioning(false);
}, 1000); // Slightly longer for smoother transition
}, 6000); // Increased interval for slower changes
return () => clearInterval(interval);
}, [carouselTexts.length]);
const currentText = carouselTexts[currentTextIndex];
if (!currentText) {
return null;
}
return (
<>
<section className="modern-banner">
<div className="banner-background">
<div className="gradient-orb orb-1"></div>
<div className="gradient-orb orb-2"></div>
<div className="gradient-orb orb-3"></div>
{/* Industrial Enterprise Background Elements */}
<div className="enterprise-bg-elements">
{/* Flying Code Elements */}
<div className="flying-code">
<div className="code-snippet code-1">
<span className="code-line">const enterprise = {'{'}</span>
<span className="code-line"> security: &apos;enterprise-grade&apos;,</span>
<span className="code-line"> scalability: &apos;unlimited&apos;</span>
<span className="code-line">{'}'};</span>
</div>
<div className="code-snippet code-2">
<span className="code-line">if (security === &apos;max&apos;) {'{'}</span>
<span className="code-line"> deploy.enterprise();</span>
<span className="code-line">{'}'}</span>
</div>
<div className="code-snippet code-3">
<span className="code-line">class EnterpriseSoftware {'{'}</span>
<span className="code-line"> constructor() {'{'}</span>
<span className="code-line"> this.secure = true;</span>
<span className="code-line"> {'}'}</span>
<span className="code-line">{'}'}</span>
</div>
<div className="code-snippet code-4">
<span className="code-line">API.authenticate({'{'}</span>
<span className="code-line"> level: &apos;enterprise&apos;,</span>
<span className="code-line"> encryption: &apos;AES-256&apos;</span>
<span className="code-line">{'}'});</span>
</div>
</div>
{/* Industrial Grid */}
<div className="industrial-grid">
<div className="grid-line horizontal h-1"></div>
<div className="grid-line horizontal h-2"></div>
<div className="grid-line horizontal h-3"></div>
<div className="grid-line horizontal h-4"></div>
<div className="grid-line vertical v-1"></div>
<div className="grid-line vertical v-2"></div>
<div className="grid-line vertical v-3"></div>
<div className="grid-line vertical v-4"></div>
</div>
{/* Security Elements */}
<div className="security-elements">
<div className="shield shield-1">
<i className="fa-solid fa-shield-halved"></i>
</div>
<div className="shield shield-2">
<i className="fa-solid fa-lock"></i>
</div>
<div className="shield shield-3">
<i className="fa-solid fa-key"></i>
</div>
<div className="shield shield-4">
<i className="fa-solid fa-fingerprint"></i>
</div>
</div>
{/* Circuit Patterns */}
<div className="circuit-patterns">
<div className="circuit circuit-1">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
<div className="circuit circuit-2">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
<div className="circuit circuit-3">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
</div>
{/* Data Streams */}
<div className="data-streams">
<div className="stream stream-1">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
<div className="stream stream-2">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
<div className="stream stream-3">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
</div>
{/* Request/Response Data */}
<div className="request-response-data">
<div className="api-request req-1">
<div className="request-label">POST /api/enterprise</div>
<div className="request-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-response resp-1">
<div className="response-label">200 OK</div>
<div className="response-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-request req-2">
<div className="request-label">GET /api/analytics</div>
<div className="request-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-response resp-2">
<div className="response-label">201 Created</div>
<div className="response-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
</div>
{/* Space Data Generation */}
<div className="space-data-generation">
<div className="data-cluster cluster-1">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-2">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-3">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-4">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
</div>
{/* Database Connections */}
<div className="database-connections">
<div className="db-connection conn-1">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-database"></i>
</div>
<div className="connection-pulse"></div>
</div>
<div className="db-connection conn-2">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-server"></i>
</div>
<div className="connection-pulse"></div>
</div>
<div className="db-connection conn-3">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-cloud"></i>
</div>
<div className="connection-pulse"></div>
</div>
</div>
{/* Real-time Metrics */}
<div className="real-time-metrics">
<div className="metric metric-1">
<div className="metric-label">API Calls/sec</div>
<div className="metric-value">2,847</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
<div className="metric metric-2">
<div className="metric-label">Data Processed</div>
<div className="metric-value">15.2TB</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
<div className="metric metric-3">
<div className="metric-label">Active Users</div>
<div className="metric-value">45,892</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
</div>
</div>
</div>
<div className="container">
<div className="banner-content">
<div className="content-center">
<div className="badge-container">
<span className="badge">
<i className={currentText.icon}></i>
{currentText.badge}
</span>
</div>
<h1 className={`main-heading carousel-text ${isTransitioning ? 'fade-out' : 'fade-in'}`}>
{currentText.heading}
<span className="gradient-text"> {currentText.highlight}</span>
<br />
{currentText.subheading}
</h1>
<p className={`description carousel-text ${isTransitioning ? 'fade-out' : 'fade-in'}`}>
{currentText.description}
</p>
{/* Carousel Indicators */}
<div className="carousel-indicators">
{carouselTexts.map((_, index) => (
<button
key={index}
className={`indicator ${index === currentTextIndex ? 'active' : ''}`}
onClick={() => {
if (index !== currentTextIndex) {
setIsTransitioning(true);
setTimeout(() => {
setCurrentTextIndex(index);
setIsTransitioning(false);
}, 1000);
}
}}
/>
))}
</div>
<div className="cta-section">
<Link href={currentText.button_url || "#"} className="cta-primary">
<span>{currentText.button_text || "Learn More"}</span>
<i className="fa-solid fa-arrow-right"></i>
</Link>
<Link href="contact-us" className="cta-secondary">
<i className="fa-solid fa-phone"></i>
<span>Contact Sales</span>
</Link>
</div>
<div className="trust-indicators">
<div className="trust-item">
<div className="trust-number">30+</div>
<div className="trust-label">Enterprise Clients</div>
</div>
<div className="trust-item">
<div className="trust-number">99.9%</div>
<div className="trust-label">Uptime SLA</div>
</div>
<div className="trust-item">
<div className="trust-number">24/7</div>
<div className="trust-label">Enterprise Support</div>
</div>
</div>
</div>
</div>
</div>
<div className="scroll-indicator" onClick={() => window.scrollTo({ top: window.innerHeight, behavior: 'smooth' })}>
<div className="scroll-text">Scroll to explore</div>
<div className="scroll-arrow">
<i className="fa-solid fa-chevron-down"></i>
</div>
</div>
</section>
</>
);
};
export default HomeBanner;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const HomeInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default HomeInitAnimations;

View File

@@ -0,0 +1,434 @@
"use client";
import Image from "next/legacy/image";
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";
const HomeLatestPost = () => {
return (
<section className="tp-latest-post pt-120 pb-120 bg-quinary">
<div className="container">
<div className="row vertical-column-gap align-items-center">
<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
</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>
</div>
</div>
</div>
<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>
</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>
</div>
</div>
</div>
</div>
</section>
);
};
export default HomeLatestPost;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const HomeScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default HomeScrollProgressButton;

View File

@@ -0,0 +1,121 @@
"use client";
import Image from "next/legacy/image";
import Link from "next/link";
import { useMemo } from "react";
import { useServices } from "@/lib/hooks/useServices";
import { serviceUtils } from "@/lib/api/serviceService";
import one from "@/public/images/overview/one.png";
import two from "@/public/images/overview/two.png";
import three from "@/public/images/overview/three.png";
import four from "@/public/images/overview/four.png";
import five from "@/public/images/overview/five.png";
// Default images array for fallback
const defaultImages = [one, two, three, four, five];
const Overview = () => {
// Memoize the parameters to prevent infinite re-renders
const serviceParams = useMemo(() => ({
ordering: 'display_order',
page: 1
}), []);
// Fetch services from API, limit to 5 for overview section
const { services, loading, error } = useServices(serviceParams);
// Get first 5 services for the overview
const displayServices = services.slice(0, 5);
return (
<section
className="tp-overview pt-120 pb-120 sticky-wrapper"
id="scroll-to"
>
<div className="container">
<div className="row vertical-column-gap-lg">
<div className="col-12 col-lg-5">
<div className="tp-overview__content sticky-item">
<h2 className="fw-7 text-secondary title-anim mb-30 mt-8">
Enterprise Solutions That Scale
</h2>
<p className="mt-8 cur-lg">
Our enterprise software development teams deliver mission-critical solutions
for Fortune 500 companies. We design, build, and deploy scalable systems
that transform your business operations, enhance security, and drive digital
innovation across your organization.
</p>
<div className="mt-40">
<Link href="services" className="btn-line text-uppercase">
EXPLORE SOLUTIONS
</Link>
</div>
</div>
</div>
<div className="col-12 col-lg-7 col-xxl-6 offset-xxl-1">
<div className="tp-overview__items sticky-item">
{loading ? (
// Loading state
<div className="text-center py-5">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="mt-3 text-muted">Loading services...</p>
</div>
) : error ? (
// Error state
<div className="text-center py-5">
<p className="text-danger">Failed to load services. Please try again later.</p>
</div>
) : displayServices.length === 0 ? (
// No services state
<div className="text-center py-5">
<p className="text-muted">No services available at the moment.</p>
</div>
) : (
// Services list
displayServices.map((service, index) => {
// Always use hardcoded images, not API images
const serviceImage = defaultImages[index] || defaultImages[0];
return (
<div key={service.id} className="tp-overview-single appear-down">
<div className="thumb">
<Image
src={serviceImage}
width={80}
height={80}
alt={service.title}
/>
</div>
<div className="wrapper">
<div className="content">
<h4 className="mt-8 mb-12 fw-6 text-secondary">
<Link href={`/services/${service.slug}`}>
{service.title}
</Link>
</h4>
<p className="text-tertiary">
{service.short_description || service.description}
</p>
</div>
<div className="cta">
<Link href={`/services/${service.slug}`}>
<span className="material-symbols-outlined">
call_made
</span>
</Link>
</div>
</div>
</div>
);
})
)}
</div>
</div>
</div>
</div>
</section>
);
};
export default Overview;

View File

@@ -0,0 +1,54 @@
import Image from "next/legacy/image";
import Link from "next/link";
import thumb from "@/public/images/service/one.png";
const ServiceIntro = () => {
return (
<section className="tp-service pt-120 pb-120">
<div className="container">
<div className="row vertical-column-gap-md">
<div className="col-12 col-lg-5">
<div className="tp-service__thumb fade-img">
<Link href="service-single" className="w-100">
<div className="parallax-image-wrap">
<div className="parallax-image-inner">
<Image
src={thumb}
className="w-100 mh-300 parallax-image"
alt="Image"
/>
</div>
</div>
</Link>
</div>
</div>
<div className="col-12 col-lg-7 col-xl-6 offset-xl-1">
<div className="tp-service__content">
<h2 className="mt-8 title-anim text-secondary fw-7 mb-30 text-capitalize">
Leading Enterprise Software Solutions Provider.
</h2>
<div className="pl-100">
<p className="cur-lg">
Transform your enterprise with cutting-edge software solutions,
system integrations, and digital transformation services. We help
Fortune 500 companies modernize their technology infrastructure,
enhance security, and achieve operational excellence through
innovative software development.
</p>
<div className="mt-60">
<Link href="service-single" className="btn-anim btn-anim-light">
Our Solutions
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default ServiceIntro;

View File

@@ -0,0 +1,136 @@
"use client";
import { useState, useEffect } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
import { getValidImageUrl, FALLBACK_IMAGES } from "@/lib/imageUtils";
const Story = () => {
const [activeIndex, setActiveIndex] = useState(0);
const [activeImageIndex, setActiveImageIndex] = useState(0);
// Static case studies data
const storyData = [
{
id: 1,
destination: "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",
display_order: 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 2,
destination: "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",
display_order: 2,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 3,
destination: "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",
display_order: 3,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 4,
destination: "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",
display_order: 4,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
},
{
id: 5,
destination: "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",
display_order: 5,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
];
const handleMouseEnter = (index: number) => {
setActiveIndex(index);
setActiveImageIndex(index);
};
return (
<section className="tp-story pt-120 pb-120 bg-black sticky-wrapper fade-wrapper">
<div className="container">
<div className="row vertical-column-gap-md">
<div className="col-12 col-lg-5">
<div className="tp-story__content sticky-item">
<h2 className="mt-8 title-anim text-white fw-7">
Enterprise Case Studies
</h2>
<div className="tp-story__items">
{storyData.map((item, index) => {
return (
<div
key={index}
className={`tp-story__single fade-top ${
index === activeIndex ? "active" : ""
}`}
onMouseEnter={() => handleMouseEnter(index)}
>
<p className="fw-6 mt-8">
<Link href={`${item.path}`}>{item.destination}</Link>
</p>
<h5 className="fw-4 mt-12 mb-12 text-white">
{item.title}
</h5>
<p className="text-xs">{item.subtitle}</p>
</div>
);
})}
</div>
</div>
</div>
<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) => {
return (
<div
key={index}
className={`tp-story-thumb ${
index === activeImageIndex ? "thumb-active" : ""
}`}
>
<Image
src={getValidImageUrl(item.image, FALLBACK_IMAGES.CASE_STUDY)}
width={600}
height={300}
className="w-100 mh-300"
alt="Image"
/>
</div>
);
})}
</div>
</div>
</div>
</div>
</section>
);
};
export default Story;

View File

@@ -0,0 +1,104 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { Service } from "@/lib/api/serviceService";
interface ServiceDeliverablesProps {
service: Service;
}
const ServiceDeliverables = ({ service }: ServiceDeliverablesProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Modern entrance animations
gsap.set(".deliverable-item", {
y: 60,
opacity: 0,
scale: 0.9,
});
ScrollTrigger.batch(".deliverable-item", {
start: "-150px bottom",
onEnter: (elements) =>
gsap.to(elements, {
y: 0,
opacity: 1,
scale: 1,
stagger: {
amount: 0.6,
from: "start"
},
duration: 1,
ease: "power3.out",
}),
});
// Animate section header
gsap.fromTo(".section-header",
{
y: 40,
opacity: 0
},
{
y: 0,
opacity: 1,
duration: 1,
ease: "power3.out",
scrollTrigger: {
trigger: ".section-header",
start: "-100px bottom"
}
}
);
}, []);
if (!service.deliverables) {
return null;
}
const deliverablesList = service.deliverables
.split(/[,;•\n]/)
.map(item => item.trim())
.filter(item => item.length > 0);
return (
<section className="enterprise-deliverables py-4">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="section-header text-center mb-4">
<span className="enterprise-section-tag">What You Get</span>
<h2 className="enterprise-section-title mb-3">
What You Get with {service.title}
</h2>
<p className="enterprise-section-description">
{service.deliverables_description || `Our comprehensive ${service.title.toLowerCase()} service includes everything you need for success`}
</p>
</div>
<div className="row g-5">
{deliverablesList.map((deliverable, index) => (
<div key={index} className="col-12 col-md-6 col-lg-4">
<div className="deliverable-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-check-circle"></i>
</div>
<div className="card-content">
<h6 className="card-title">
{deliverable}
</h6>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</section>
);
};
export default ServiceDeliverables;

View File

@@ -0,0 +1,138 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Image from "next/legacy/image";
import { Service } from "@/lib/api/serviceService";
import { serviceUtils } from "@/lib/api/serviceService";
interface ServiceDetailsProps {
service: Service;
}
const ServiceDetails = ({ service }: ServiceDetailsProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Animate content on scroll
gsap.set(".detail-content", {
x: -50,
opacity: 0,
});
gsap.set(".detail-image", {
x: 50,
opacity: 0,
});
ScrollTrigger.batch(".detail-content, .detail-image", {
start: "-100px bottom",
onEnter: (elements) =>
gsap.to(elements, {
x: 0,
opacity: 1,
duration: 0.8,
ease: "power2.out",
}),
});
}, []);
return (
<section id="service-details" className="enterprise-details py-5">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="row align-items-center">
<div className="col-12 col-lg-6">
<div className="detail-content">
<div className="section-header mb-5">
<span className="enterprise-section-tag">About Service</span>
<h2 className="enterprise-section-title mb-4">
About Our {service.title}
</h2>
{service.short_description && (
<p className="enterprise-section-description">
{service.short_description}
</p>
)}
</div>
<div className="enterprise-stats mb-4">
<div className="row g-3">
<div className="col-6">
<div className="enterprise-stat-card">
<div className="stat-icon">
<i className="fa-solid fa-star"></i>
</div>
<div className="stat-content">
<div className="stat-number">
{service.featured ? 'Featured' : 'Standard'}
</div>
<div className="stat-label">Service Type</div>
</div>
</div>
</div>
<div className="col-6">
<div className="enterprise-stat-card">
<div className="stat-icon">
<i className="fa-solid fa-dollar-sign"></i>
</div>
<div className="stat-content">
<div className="stat-number">
{service.formatted_price}
</div>
<div className="stat-label">Starting Price</div>
</div>
</div>
</div>
</div>
</div>
<div className="enterprise-meta mb-4">
<div className="meta-item">
<div className="meta-icon">
<i className="fa-solid fa-tag"></i>
</div>
<div className="meta-content">
<span className="meta-label">Category</span>
<span className="meta-value">{service.category?.name || 'General'}</span>
</div>
</div>
{service.duration && (
<div className="meta-item">
<div className="meta-icon">
<i className="fa-solid fa-clock"></i>
</div>
<div className="meta-content">
<span className="meta-label">Duration</span>
<span className="meta-value">{service.duration}</span>
</div>
</div>
)}
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="detail-image">
<div className="enterprise-image-wrapper">
<Image
src={serviceUtils.getServiceImageUrl(service) || '/images/service/default.png'}
alt={service.title}
width={600}
height={400}
className="enterprise-service-image"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default ServiceDetails;

View File

@@ -0,0 +1,102 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { Service, ServiceFeature } from "@/lib/api/serviceService";
interface ServiceFeaturesProps {
service: Service;
}
const ServiceFeatures = ({ service }: ServiceFeaturesProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Modern entrance animations
gsap.set(".feature-item", {
y: 60,
opacity: 0,
scale: 0.9,
});
ScrollTrigger.batch(".feature-item", {
start: "-150px bottom",
onEnter: (elements) =>
gsap.to(elements, {
y: 0,
opacity: 1,
scale: 1,
stagger: {
amount: 0.6,
from: "start"
},
duration: 1,
ease: "power3.out",
}),
});
// Animate section header
gsap.fromTo(".section-header",
{
y: 40,
opacity: 0
},
{
y: 0,
opacity: 1,
duration: 1,
ease: "power3.out",
scrollTrigger: {
trigger: ".section-header",
start: "-100px bottom"
}
}
);
}, []);
if (!service.features || service.features.length === 0) {
return null;
}
return (
<section className="enterprise-features py-4">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="section-header text-center mb-4">
<span className="enterprise-section-tag">Key Features</span>
<h2 className="enterprise-section-title mb-3">
{service.title} Features
</h2>
<p className="enterprise-section-description">
{service.features_description || `Discover the key features that make our ${service.title.toLowerCase()} service stand out from the competition`}
</p>
</div>
<div className="row g-5">
{service.features.map((feature: ServiceFeature, index: number) => (
<div key={feature.id} className="col-12 col-md-6 col-lg-4">
<div className="feature-item enterprise-section-card">
<div className="card-icon">
<i className={`fa-solid fa-${feature.icon || 'check'}`}></i>
</div>
<div className="card-content">
<h6 className="card-title">
{feature.title}
</h6>
<p className="card-description">
{feature.description}
</p>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</section>
);
};
export default ServiceFeatures;

View File

@@ -0,0 +1,158 @@
"use client";
import { useState, useEffect } from "react";
import Image from "next/legacy/image";
import Link from "next/link";
import { getValidImageUrl, FALLBACK_IMAGES } from "@/lib/imageUtils";
import { useServices } from "@/lib/hooks/useServices";
import { serviceUtils } from "@/lib/api/serviceService";
const ServiceMain = () => {
// Fetch services from API
const { services, loading, error } = useServices();
// Show loading state
if (loading) {
return (
<section className="tp-service pt-120 fade-wrapper" id="scroll-to">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center">
<div className="spinner-border" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<p className="mt-3">Loading services...</p>
</div>
</div>
</div>
</div>
</section>
);
}
// Show error state
if (error) {
return (
<section className="tp-service pt-120 fade-wrapper" id="scroll-to">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center">
<div className="alert alert-danger" role="alert">
<h4>Error Loading Services</h4>
<p>{error}</p>
<button
className="btn btn-primary"
onClick={() => window.location.reload()}
>
Try Again
</button>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
// Show empty state
if (!services || services.length === 0) {
return (
<section className="tp-service pt-120 fade-wrapper" id="scroll-to">
<div className="container">
<div className="row">
<div className="col-12">
<div className="text-center">
<h3>No Services Available</h3>
<p>We&apos;re working on adding new services. Please check back later.</p>
</div>
</div>
</div>
</div>
</section>
);
}
return (
<section className="enterprise-services py-5" id="scroll-to">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="section-header text-center mb-5">
<span className="enterprise-section-tag">Our Services</span>
<h2 className="enterprise-section-title mb-4">
Professional Software Development Services
</h2>
<p className="enterprise-section-description">
We deliver comprehensive technology solutions tailored to your business needs
</p>
</div>
</div>
</div>
<div className="row g-4">
{services.map((service, index) => (
<div key={service.id} className="col-12 col-lg-6 col-xl-4">
<div className="enterprise-service-card">
<div className="service-image-wrapper">
<Link href={`/services/${service.slug}`}>
<Image
src={getValidImageUrl(serviceUtils.getServiceImageUrl(service), FALLBACK_IMAGES.SERVICE)}
alt={service.title}
width={400}
height={300}
className="service-image"
/>
</Link>
<div className="service-overlay">
<Link href={`/services/${service.slug}`} className="btn btn-primary">
<span>Learn More</span>
<i className="fa-solid fa-arrow-right ms-2"></i>
</Link>
</div>
</div>
<div className="service-content">
<div className="service-meta">
<span className="service-number">
{String(index + 1).padStart(2, '0')}
</span>
{service.category && (
<span className="service-category">
{service.category.name}
</span>
)}
</div>
<h3 className="service-title">
<Link href={`/services/${service.slug}`}>
{service.title}
</Link>
</h3>
<p className="service-description">
{service.short_description || service.description}
</p>
<div className="service-footer">
<div className="service-price">
{service.formatted_price}
</div>
<Link href={`/services/${service.slug}`} className="service-link">
<span>View Details</span>
<i className="fa-solid fa-arrow-right"></i>
</Link>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
};
export default ServiceMain;

View File

@@ -0,0 +1,154 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Link from "next/link";
import { Service } from "@/lib/api/serviceService";
interface ServicePricingProps {
service: Service;
}
const ServicePricing = ({ service }: ServicePricingProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Animate pricing section
gsap.set(".pricing-content", {
y: 50,
opacity: 0,
});
ScrollTrigger.create({
trigger: ".pricing-content",
start: "-100px bottom",
onEnter: () =>
gsap.to(".pricing-content", {
y: 0,
opacity: 1,
duration: 0.8,
ease: "power2.out",
}),
});
}, []);
return (
<section className="enterprise-pricing py-5">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="row">
<div className="col-12 col-lg-8 offset-lg-2">
<div className="section-header text-center mb-5">
<span className="enterprise-section-tag">Pricing & Packages</span>
<h2 className="enterprise-section-title mb-4">
Pricing & Packages
</h2>
<p className="enterprise-section-description">
Get started with our {service.title.toLowerCase()} service.
Contact us for a customized quote based on your specific requirements.
</p>
</div>
<div className="pricing-content text-center">
<div className="enterprise-pricing-card">
<div className="pricing-header">
<div className="pricing-badge">
<span>Most Popular</span>
</div>
<h3 className="pricing-title">
{service.title}
</h3>
<div className="price-display">
<span className="price-amount">
{service.formatted_price}
</span>
<span className="price-period">
Starting Price
</span>
</div>
</div>
<div className="pricing-features">
<ul className="enterprise-feature-list">
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-check"></i>
</div>
<span>Custom {service.title.toLowerCase()} solution</span>
</li>
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-check"></i>
</div>
<span>Professional consultation</span>
</li>
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-check"></i>
</div>
<span>Ongoing support & maintenance</span>
</li>
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-check"></i>
</div>
<span>Quality assurance & testing</span>
</li>
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-check"></i>
</div>
<span>Documentation & training</span>
</li>
{service.duration && (
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-clock"></i>
</div>
<span>Project duration: {service.duration}</span>
</li>
)}
{service.technologies && (
<li className="feature-item">
<div className="feature-icon">
<i className="fa-solid fa-code"></i>
</div>
<span>Latest technologies & frameworks</span>
</li>
)}
</ul>
</div>
<div className="pricing-cta">
<Link href="/contact-us" className="btn btn-primary btn-lg me-3 mb-3">
<span>Get Free Quote</span>
<i className="fa-solid fa-arrow-right ms-2"></i>
</Link>
<Link href="/services" className="btn btn-outline-secondary btn-lg mb-3">
<span>View All Services</span>
</Link>
</div>
</div>
<div className="pricing-note">
<div className="note-content">
<i className="fa-solid fa-info-circle"></i>
<p>
Final pricing depends on project scope, complexity, and specific requirements.
Contact us for a detailed proposal.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default ServicePricing;

View File

@@ -0,0 +1,130 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { Service } from "@/lib/api/serviceService";
interface ServiceProcessProps {
service: Service;
}
const ServiceProcess = ({ service }: ServiceProcessProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Modern entrance animations
gsap.set(".process-step", {
y: 60,
opacity: 0,
scale: 0.9,
});
ScrollTrigger.batch(".process-step", {
start: "-150px bottom",
onEnter: (elements) =>
gsap.to(elements, {
y: 0,
opacity: 1,
scale: 1,
stagger: {
amount: 0.6,
from: "start"
},
duration: 1,
ease: "power3.out",
}),
});
// Animate section header
gsap.fromTo(".section-header",
{
y: 40,
opacity: 0
},
{
y: 0,
opacity: 1,
duration: 1,
ease: "power3.out",
scrollTrigger: {
trigger: ".section-header",
start: "-100px bottom"
}
}
);
}, []);
if (!service.process_steps) {
return null;
}
// Split process steps by common separators
const processSteps = service.process_steps
.split(/[,;•\n]/)
.map(step => step.trim())
.filter(step => step.length > 0);
return (
<section className="enterprise-process py-4">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="section-header text-center mb-4">
<span className="enterprise-section-tag">Our Process</span>
<h2 className="enterprise-section-title mb-3">
{service.title} Process
</h2>
<p className="enterprise-section-description">
{service.process_description || `Our proven methodology ensures successful delivery of your ${service.title.toLowerCase()} project.`}
</p>
</div>
<div className="row g-5">
{processSteps.map((step, index) => (
<div key={index} className="col-12 col-md-6 col-lg-4">
<div className="process-step enterprise-process-step-compact">
<div className="step-number">
<span className="step-number-text">
{String(index + 1).padStart(2, '0')}
</span>
</div>
<div className="step-content">
<h6 className="step-title">
{step}
</h6>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</section>
);
};
// Helper function to generate step descriptions based on step name and service
const getStepDescription = (step: string, serviceTitle: string): string => {
const descriptions: { [key: string]: string } = {
'Requirements Analysis': 'We analyze your business requirements and technical specifications to ensure we understand your goals.',
'System Design': 'Our team creates a comprehensive system architecture and design that meets your specific needs.',
'Development': 'We implement the solution using industry best practices and modern technologies.',
'Testing': 'Rigorous testing ensures your solution is reliable, secure, and performs optimally.',
'Deployment': 'We handle the deployment process and ensure smooth transition to production.',
'Training': 'We provide comprehensive training to your team for successful adoption.',
'API Planning': 'We design the API architecture and define endpoints based on your integration needs.',
'API Development': 'We build robust, scalable APIs using modern frameworks and best practices.',
'Documentation': 'Comprehensive API documentation ensures easy integration and maintenance.',
'Integration': 'We integrate the API with your existing systems and third-party services.',
'Assessment': 'We evaluate your current infrastructure and identify migration opportunities.',
'Migration Planning': 'We create a detailed migration strategy with minimal downtime.',
'Implementation': 'We execute the migration plan with careful monitoring and rollback procedures.',
'Optimization': 'We optimize your cloud infrastructure for performance and cost efficiency.',
'Support': 'Ongoing support and maintenance ensure your solution continues to perform optimally.'
};
return descriptions[step] || `This step involves ${step.toLowerCase()} to ensure the success of your ${serviceTitle.toLowerCase()} project.`;
};
export default ServiceProcess;

View File

@@ -0,0 +1,137 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Image from "next/legacy/image";
import Link from "next/link";
import thumbOne from "@/public/images/service/thumb-one.png";
import thumbTwo from "@/public/images/service/thumb-two.png";
const ServicesBanner = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
if (document.querySelector(".service-banner")) {
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".service-banner",
start: "center center",
end: "+=100%",
scrub: true,
pin: false,
},
});
tl.to(".thumb-one", {
opacity: 0.3,
y: "-100%",
zIndex: -1,
duration: 2,
});
tl.to(
".thumb-two",
{
opacity: 0.3,
scale: 2,
y: "100%",
zIndex: -1,
duration: 2,
},
0
);
}
}, []);
return (
<section className="enterprise-banner position-relative overflow-hidden">
<div className="banner-background">
<div className="gradient-overlay"></div>
<div className="geometric-pattern"></div>
</div>
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="enterprise-banner__content">
<div className="banner-badge mb-4">
<span className="enterprise-badge">
Professional Services
</span>
</div>
<h1 className="enterprise-title mb-4">
The end-to-end bespoke software development agency you need
</h1>
<p className="enterprise-description mb-5">
Empower your business with sophisticated tech solutions by GNX.
From ideation to implementation, with a team of experts right at your fingertips
</p>
<div className="enterprise-cta">
<Link href="/contact-us" className="btn btn-primary btn-lg me-3 mb-3">
<span>Get Free Quote</span>
<i className="fa-solid fa-arrow-right ms-2"></i>
</Link>
<Link href="#scroll-to" className="btn btn-outline-light btn-lg mb-3">
<span>Explore Services</span>
<i className="fa-solid fa-arrow-down ms-2"></i>
</Link>
</div>
</div>
</div>
</div>
</div>
<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>
<Link href="#scroll-to" className="scroll-to">
Scroll
<span className="arrow"></span>
</Link>
<div className="thumb-one">
<Image src={thumbOne} alt="Image" width={600} height={400} />
</div>
<div className="thumb-two">
<Image src={thumbTwo} alt="Image" width={600} height={400} />
</div>
</section>
);
};
export default ServicesBanner;

View File

@@ -0,0 +1,65 @@
"use client";
import dynamic from "next/dynamic";
const SmoothScroll = dynamic(() => import("../../shared/layout/animations/SmoothScroll"), {
ssr: false,
});
const ParallaxImage = dynamic(() => import("../../shared/layout/animations/ParallaxImage"), {
ssr: false,
});
const FadeImageBottom = dynamic(() => import("../../shared/layout/animations/FadeImageBottom"), {
ssr: false,
});
const ButtonHoverAnimation = dynamic(
() => import("../../shared/layout/animations/ButtonHoverAnimation"),
{
ssr: false,
}
);
const VanillaTiltHover = dynamic(
() => import("../../shared/layout/animations/VanillaTiltHover"),
{
ssr: false,
}
);
const SplitTextAnimations = dynamic(
() => import("../../shared/layout/animations/SplitTextAnimations"),
{
ssr: false,
}
);
const ScrollToElement = dynamic(() => import("../../shared/layout/animations/ScrollToElement"), {
ssr: false,
});
const AppearDown = dynamic(() => import("../../shared/layout/animations/AppearDown"), {
ssr: false,
});
const FadeAnimations = dynamic(() => import("../../shared/layout/animations/FadeAnimations"), {
ssr: false,
});
const ServicesInitAnimations = () => {
return (
<>
<SmoothScroll />
<ParallaxImage />
<FadeImageBottom />
<ButtonHoverAnimation />
<VanillaTiltHover />
<SplitTextAnimations />
<ScrollToElement />
<AppearDown />
<FadeAnimations />
</>
);
};
export default ServicesInitAnimations;

View File

@@ -0,0 +1,67 @@
"use client";
import { useState, useEffect, useRef } from "react";
const ServicesScrollProgressButton = () => {
useEffect(() => {
window.scroll(0, 0);
}, []);
const [scrollProgress, setScrollProgress] = useState(0);
const [isActive, setIsActive] = useState(false);
const scrollRef = useRef<HTMLButtonElement>(null);
const handleScroll = () => {
const totalHeight = document.body.scrollHeight - window.innerHeight;
const progress = (window.scrollY / totalHeight) * 100;
setScrollProgress(progress);
setIsActive(window.scrollY > 50);
};
const handleProgressClick = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
useEffect(() => {
window.scrollTo(0, 0);
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<button
ref={scrollRef}
className={`progress-wrap ${isActive ? " active-progress" : " "}`}
onClick={handleProgressClick}
title="Go To Top"
>
<span></span>
<svg
className="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path
d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"
stroke="#3887FE"
strokeWidth="4"
fill="none"
style={{
strokeDasharray: "308.66px",
strokeDashoffset: `${308.66 - scrollProgress * 3.0866}px`,
}}
/>
</svg>
</button>
);
};
export default ServicesScrollProgressButton;

View File

@@ -0,0 +1,228 @@
"use client";
import { useEffect } from "react";
import Image from "next/legacy/image";
import gsap from "gsap";
import ScrollTrigger from "gsap/dist/ScrollTrigger";
import thumb from "@/public/images/transform-thumb.png";
import teamThumb from "@/public/images/team-thumb.png";
import { Service } from "@/lib/api/serviceService";
import { serviceUtils } from "@/lib/api/serviceService";
interface TransformProps {
service: Service;
}
const Transform = ({ service }: TransformProps) => {
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,
}),
});
}, []);
return (
<section className="enterprise-transform py-5" id="scroll-to">
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="row align-items-center mb-5">
<div className="col-12 col-lg-6">
<div className="transform__content">
<div className="section-header mb-4">
<span className="enterprise-section-tag">Transform Your Business</span>
<h2 className="enterprise-section-title mb-4">
Transform your business with {service.title}
</h2>
<p className="enterprise-section-description">
{service.description}
</p>
{service.formatted_price && (
<div className="mt-4">
<div className="price-highlight">
<span className="price-label">Starting from</span>
<span className="price-value">{service.formatted_price}</span>
</div>
</div>
)}
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="transform__thumb">
<div className="enterprise-image-wrapper">
<Image
src={serviceUtils.getServiceImageUrl(service) || thumb}
className="enterprise-service-image"
alt={service.title}
width={600}
height={400}
/>
</div>
</div>
</div>
</div>
<div className="section-header text-center mb-4">
<span className="enterprise-section-tag">Why Choose Us</span>
<h2 className="enterprise-section-title mb-3">
{service.why_choose_description || `Why choose our ${service.title.toLowerCase()}?`}
</h2>
</div>
<div className="row g-5">
{service.features && service.features.length > 0 ? (
service.features.slice(0, 6).map((feature, index) => (
<div key={feature.id} className="col-12 col-md-6 col-lg-4">
<div className="benefit-item enterprise-section-card">
<div className="card-icon">
<i className={`fa-solid fa-${feature.icon || 'check'}`}></i>
</div>
<div className="card-content">
<h6 className="card-title">{feature.title}</h6>
<p className="card-description">
{feature.description}
</p>
</div>
</div>
</div>
))
) : (
// Fallback content if no features are available
<>
<div className="col-12 col-md-6 col-lg-4">
<div className="benefit-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-rocket"></i>
</div>
<div className="card-content">
<h6 className="card-title">Fast Delivery</h6>
<p className="card-description">
{service.duration ? `Delivered in ${service.duration}` : 'Quick turnaround times for your project needs'}
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="benefit-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-shield-halved"></i>
</div>
<div className="card-content">
<h6 className="card-title">Quality Assured</h6>
<p className="card-description">
Rigorous testing and quality control ensure reliable, robust solutions
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="benefit-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-headset"></i>
</div>
<div className="card-content">
<h6 className="card-title">Ongoing Support</h6>
<p className="card-description">
Comprehensive support and maintenance to ensure optimal performance
</p>
</div>
</div>
</div>
</>
)}
</div>
<div className="section-header text-center mb-4 mt-6">
<span className="enterprise-section-tag">Our Expertise</span>
<h2 className="enterprise-section-title mb-3">
Our Expertise
</h2>
{service.expertise_description && (
<p className="enterprise-section-description">
{service.expertise_description}
</p>
)}
</div>
<div className="row g-5">
{service.expertise_items && service.expertise_items.length > 0 ? (
service.expertise_items.slice(0, 3).map((expertise, index) => (
<div key={expertise.id} className="col-12 col-md-6 col-lg-4">
<div className="expertise-item enterprise-section-card">
<div className="card-icon">
<i className={`fa-solid fa-${expertise.icon || 'star'}`}></i>
</div>
<div className="card-content">
<h6 className="card-title">{expertise.title}</h6>
<p className="card-description">
{expertise.description}
</p>
</div>
</div>
</div>
))
) : (
// Fallback content if no expertise items are available
<>
<div className="col-12 col-md-6 col-lg-4">
<div className="expertise-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-users"></i>
</div>
<div className="card-content">
<h6 className="card-title">Expert Team</h6>
<p className="card-description">
Our experienced team specializes in {service.title.toLowerCase()} with years of industry expertise.
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="expertise-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-code"></i>
</div>
<div className="card-content">
<h6 className="card-title">Modern Technologies</h6>
<p className="card-description">
We use cutting-edge technologies and frameworks to deliver scalable, secure solutions.
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="expertise-item enterprise-section-card">
<div className="card-icon">
<i className="fa-solid fa-chart-line"></i>
</div>
<div className="card-content">
<h6 className="card-title">Proven Results</h6>
<p className="card-description">
We have successfully delivered solutions to numerous clients, helping them achieve their goals.
</p>
</div>
</div>
</div>
</>
)}
</div>
</div>
</div>
</div>
</section>
);
};
export default Transform;

View File

@@ -0,0 +1,401 @@
"use client";
import { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Image from "next/legacy/image";
import Link from "next/link";
import { Service } from "@/lib/api/serviceService";
import { serviceUtils } from "@/lib/api/serviceService";
interface ServiceDetailsBannerProps {
service: Service;
}
const ServiceDetailsBanner = ({ service }: ServiceDetailsBannerProps) => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
if (document.querySelector(".service-banner")) {
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".service-banner",
start: "center center",
end: "+=100%",
scrub: true,
pin: false,
},
});
tl.to(".thumb-one", {
opacity: 0.3,
y: "-100%",
zIndex: -1,
duration: 2,
});
tl.to(
".thumb-two",
{
opacity: 0.3,
scale: 2,
y: "100%",
zIndex: -1,
duration: 2,
},
0
);
}
}, []);
return (
<section className="enterprise-banner position-relative overflow-hidden">
<div className="banner-background">
<div className="gradient-orb orb-1"></div>
<div className="gradient-orb orb-2"></div>
<div className="gradient-orb orb-3"></div>
{/* Service-Specific Background Elements */}
<div className="enterprise-bg-elements">
{/* Flying Service Code Elements */}
<div className="flying-code">
<div className="code-snippet code-1">
<span className="code-line">const service = {'{'}</span>
<span className="code-line"> name: &apos;{service.title}&apos;,</span>
<span className="code-line"> category: &apos;{service.category?.name}&apos;</span>
<span className="code-line">{'}'};</span>
</div>
<div className="code-snippet code-2">
<span className="code-line">if (service.featured) {'{'}</span>
<span className="code-line"> deploy.premium();</span>
<span className="code-line">{'}'}</span>
</div>
<div className="code-snippet code-3">
<span className="code-line">class ServiceDelivery {'{'}</span>
<span className="code-line"> constructor() {'{'}</span>
<span className="code-line"> this.quality = &apos;enterprise&apos;;</span>
<span className="code-line"> {'}'}</span>
<span className="code-line">{'}'}</span>
</div>
<div className="code-snippet code-4">
<span className="code-line">API.deliver({'{'}</span>
<span className="code-line"> service: &apos;{service.title}&apos;,</span>
<span className="code-line"> duration: &apos;{service.duration}&apos;</span>
<span className="code-line">{'}'});</span>
</div>
</div>
{/* Industrial Grid */}
<div className="industrial-grid">
<div className="grid-line horizontal h-1"></div>
<div className="grid-line horizontal h-2"></div>
<div className="grid-line horizontal h-3"></div>
<div className="grid-line horizontal h-4"></div>
<div className="grid-line vertical v-1"></div>
<div className="grid-line vertical v-2"></div>
<div className="grid-line vertical v-3"></div>
<div className="grid-line vertical v-4"></div>
</div>
{/* Service Elements */}
<div className="security-elements">
<div className="shield shield-1">
<i className="fa-solid fa-cogs"></i>
</div>
<div className="shield shield-2">
<i className="fa-solid fa-rocket"></i>
</div>
<div className="shield shield-3">
<i className="fa-solid fa-chart-line"></i>
</div>
<div className="shield shield-4">
<i className="fa-solid fa-users"></i>
</div>
</div>
{/* Circuit Patterns */}
<div className="circuit-patterns">
<div className="circuit circuit-1">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
<div className="circuit circuit-2">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
<div className="circuit circuit-3">
<div className="circuit-node"></div>
<div className="circuit-line"></div>
<div className="circuit-node"></div>
</div>
</div>
{/* Data Streams */}
<div className="data-streams">
<div className="stream stream-1">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
<div className="stream stream-2">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
<div className="stream stream-3">
<div className="data-bit"></div>
<div className="data-bit"></div>
<div className="data-bit"></div>
</div>
</div>
{/* Service Request/Response Data */}
<div className="request-response-data">
<div className="api-request req-1">
<div className="request-label">POST /api/services</div>
<div className="request-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-response resp-1">
<div className="response-label">200 OK</div>
<div className="response-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-request req-2">
<div className="request-label">GET /api/delivery</div>
<div className="request-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
<div className="api-response resp-2">
<div className="response-label">201 Created</div>
<div className="response-data">
<div className="data-packet"></div>
<div className="data-packet"></div>
<div className="data-packet"></div>
</div>
</div>
</div>
{/* Service Data Generation */}
<div className="space-data-generation">
<div className="data-cluster cluster-1">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-2">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-3">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
<div className="data-cluster cluster-4">
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
<div className="data-point"></div>
</div>
</div>
{/* Service Connections */}
<div className="database-connections">
<div className="db-connection conn-1">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-cogs"></i>
</div>
<div className="connection-pulse"></div>
</div>
<div className="db-connection conn-2">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-rocket"></i>
</div>
<div className="connection-pulse"></div>
</div>
<div className="db-connection conn-3">
<div className="connection-line"></div>
<div className="db-node">
<i className="fa-solid fa-chart-line"></i>
</div>
<div className="connection-pulse"></div>
</div>
</div>
{/* Service Metrics */}
<div className="real-time-metrics">
<div className="metric metric-1">
<div className="metric-label">Service Uptime</div>
<div className="metric-value">99.9%</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
<div className="metric metric-2">
<div className="metric-label">Response Time</div>
<div className="metric-value">45ms</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
<div className="metric metric-3">
<div className="metric-label">Client Satisfaction</div>
<div className="metric-value">98%</div>
<div className="metric-bar">
<div className="bar-fill"></div>
</div>
</div>
</div>
</div>
</div>
<div className="container">
<div className="row justify-content-center">
<div className="col-12 col-xl-10">
<div className="enterprise-banner__content">
<div className="banner-badge mb-4">
<span className="enterprise-badge">
{service.category?.name || 'Professional Service'}
</span>
</div>
<h1 className="enterprise-title mb-4">
{service.title}
</h1>
<p className="enterprise-description mb-5">
{service.description}
</p>
<div className="enterprise-highlights mb-5">
<div className="row justify-content-center g-4">
{service.duration && (
<div className="col-auto">
<div className="highlight-card">
<div className="highlight-icon">
<i className="fa-solid fa-clock"></i>
</div>
<div className="highlight-content">
<span className="highlight-label">Duration</span>
<span className="highlight-value">{service.duration}</span>
</div>
</div>
</div>
)}
{service.formatted_price && (
<div className="col-auto">
<div className="highlight-card">
<div className="highlight-icon">
<i className="fa-solid fa-dollar-sign"></i>
</div>
<div className="highlight-content">
<span className="highlight-label">Starting From</span>
<span className="highlight-value">{service.formatted_price}</span>
</div>
</div>
</div>
)}
{service.featured && (
<div className="col-auto">
<div className="highlight-card featured">
<div className="highlight-icon">
<i className="fa-solid fa-star"></i>
</div>
<div className="highlight-content">
<span className="highlight-label">Premium</span>
<span className="highlight-value">Featured Service</span>
</div>
</div>
</div>
)}
</div>
</div>
<div className="enterprise-cta">
<Link href="/contact-us" className="btn btn-primary btn-lg me-3 mb-3">
<span>Get Free Quote</span>
<i className="fa-solid fa-arrow-right ms-2"></i>
</Link>
<Link href="#service-details" className="btn btn-outline-light btn-lg mb-3">
<span>Learn More</span>
<i className="fa-solid fa-arrow-down ms-2"></i>
</Link>
</div>
</div>
</div>
</div>
</div>
<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>
<Link href="#scroll-to" className="scroll-to">
Scroll
<span className="arrow"></span>
</Link>
</section>
);
};
export default ServiceDetailsBanner;

View File

@@ -0,0 +1,326 @@
'use client';
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useCookieConsent, CookiePreferences } from './CookieConsentContext';
// Cookie type definitions
interface CookieType {
id: keyof CookiePreferences;
name: string;
description: string;
required: boolean;
icon: string;
}
const cookieTypes: CookieType[] = [
{
id: 'necessary',
name: 'Necessary Cookies',
description: 'Essential cookies required for the website to function properly. These cannot be disabled.',
required: true,
icon: 'fas fa-shield-alt',
},
{
id: 'functional',
name: 'Functional Cookies',
description: 'These cookies enable enhanced functionality and personalization, such as remembering your preferences.',
required: false,
icon: 'fas fa-cogs',
},
];
// Main Cookie Consent Banner Component
export const CookieConsentBanner: React.FC = () => {
const { state, config, acceptAll, acceptNecessary, showSettings } = useCookieConsent();
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
if (state.showBanner) {
// Small delay to ensure smooth animation
const timer = setTimeout(() => setIsVisible(true), 100);
return () => clearTimeout(timer);
} else {
setIsVisible(false);
}
}, [state.showBanner]);
if (!state.showBanner || !isVisible) return null;
return (
<AnimatePresence>
<motion.div
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeOut' }}
className="cookie-consent-banner"
>
<div className="cookie-consent-banner__container">
<div className="cookie-consent-banner__content">
<div className="cookie-consent-banner__icon">
<i className="fas fa-cookie-bite"></i>
</div>
<div className="cookie-consent-banner__text">
<h3>Cookie Preferences</h3>
<p>
We use only essential functional cookies to ensure our website works properly.
We do not collect personal data or use tracking cookies. Your privacy is important to us.
</p>
{config.showPrivacyNotice && (
<div className="cookie-consent-banner__links">
<a href={config.privacyPolicyUrl} target="_blank" rel="noopener noreferrer">
Privacy Policy
</a>
<a href={config.cookiePolicyUrl} target="_blank" rel="noopener noreferrer">
Cookie Policy
</a>
</div>
)}
</div>
</div>
<div className="cookie-consent-banner__actions">
<button
type="button"
className="cookie-consent-banner__btn cookie-consent-banner__btn--secondary"
onClick={showSettings}
>
<i className="fas fa-cog"></i>
Settings
</button>
<button
type="button"
className="cookie-consent-banner__btn cookie-consent-banner__btn--primary"
onClick={acceptNecessary}
>
<i className="fas fa-check"></i>
Accept Functional Only
</button>
</div>
</div>
</motion.div>
</AnimatePresence>
);
};
// Cookie Settings Modal Component
export const CookieSettingsModal: React.FC = () => {
const { state, config, hideSettings, acceptSelected, updatePreferences, withdrawConsent, exportConsentData } = useCookieConsent();
const [tempPreferences, setTempPreferences] = useState<CookiePreferences>(state.preferences);
useEffect(() => {
setTempPreferences(state.preferences);
}, [state.preferences]);
const handlePreferenceChange = (type: keyof CookiePreferences, value: boolean) => {
if (type === 'necessary') return; // Cannot change necessary cookies
setTempPreferences(prev => ({
...prev,
[type]: value,
}));
};
const handleSavePreferences = () => {
acceptSelected(tempPreferences);
};
const handleAcceptAll = () => {
const allAccepted: CookiePreferences = {
necessary: true,
functional: true,
};
acceptSelected(allAccepted);
};
if (!state.showSettings) return null;
return (
<AnimatePresence>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="cookie-settings-overlay"
onClick={hideSettings}
>
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
transition={{ duration: 0.2 }}
className="cookie-settings-modal"
onClick={(e) => e.stopPropagation()}
>
<div className="cookie-settings-modal__header">
<div className="cookie-settings-modal__header-content">
<h2>Cookie Preferences</h2>
<p className="cookie-settings-modal__version">v{config.version}</p>
</div>
<button
type="button"
className="cookie-settings-modal__close"
onClick={hideSettings}
aria-label="Close settings"
>
<i className="fas fa-times"></i>
</button>
</div>
<div className="cookie-settings-modal__content">
<div className="cookie-settings-modal__description">
<p>
We respect your privacy and only use essential functional cookies.
You can choose which types of cookies to allow below.
</p>
</div>
<div className="cookie-settings-modal__types">
{cookieTypes.map((cookieType) => (
<div
key={cookieType.id}
className={`cookie-settings-modal__type ${
cookieType.required ? 'cookie-settings-modal__type--required' : ''
}`}
>
<div className="cookie-settings-modal__type-header">
<div className="cookie-settings-modal__type-info">
<i className={cookieType.icon}></i>
<div>
<h4>{cookieType.name}</h4>
<p>{cookieType.description}</p>
</div>
</div>
<div className="cookie-settings-modal__type-toggle">
<label className="cookie-toggle">
<input
type="checkbox"
checked={tempPreferences[cookieType.id]}
onChange={(e) => handlePreferenceChange(cookieType.id, e.target.checked)}
disabled={cookieType.required}
/>
<span className="cookie-toggle__slider"></span>
</label>
</div>
</div>
</div>
))}
</div>
<div className="cookie-settings-modal__privacy">
<h4>Privacy Information</h4>
<ul>
<li>We do not collect personal data without your explicit consent</li>
<li>Functional cookies are used only to maintain website functionality</li>
<li>We do not use tracking, analytics, or marketing cookies</li>
<li>You can change your preferences at any time</li>
<li>Data retention period: {config.retentionPeriod} days</li>
<li>Contact: <a href={`mailto:${config.dataControllerEmail}`}>{config.dataControllerEmail}</a></li>
</ul>
</div>
{config.enableDetailedSettings && (
<div className="cookie-settings-modal__enterprise">
<h4>Enterprise Features</h4>
<div className="cookie-settings-modal__enterprise-actions">
<button
type="button"
className="cookie-settings-modal__btn cookie-settings-modal__btn--outline"
onClick={() => {
const data = exportConsentData();
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `cookie-consent-data-${new Date().toISOString().split('T')[0]}.json`;
a.click();
URL.revokeObjectURL(url);
}}
>
<i className="fas fa-download"></i>
Export Data
</button>
<button
type="button"
className="cookie-settings-modal__btn cookie-settings-modal__btn--danger"
onClick={() => {
if (confirm('Are you sure you want to withdraw your consent? This will reset all preferences.')) {
withdrawConsent();
}
}}
>
<i className="fas fa-user-times"></i>
Withdraw Consent
</button>
</div>
</div>
)}
</div>
<div className="cookie-settings-modal__footer">
<button
type="button"
className="cookie-settings-modal__btn cookie-settings-modal__btn--secondary"
onClick={hideSettings}
>
Cancel
</button>
<button
type="button"
className="cookie-settings-modal__btn cookie-settings-modal__btn--primary"
onClick={handleSavePreferences}
>
Save Preferences
</button>
</div>
</motion.div>
</motion.div>
</AnimatePresence>
);
};
// Main Cookie Consent Component that combines both banner and modal
export const CookieConsent: React.FC = () => {
return (
<>
<CookieConsentBanner />
<CookieSettingsModal />
</>
);
};
// Cookie Preferences Display Component (for footer or privacy page)
export const CookiePreferencesDisplay: React.FC = () => {
const { state, showSettings, resetConsent } = useCookieConsent();
return (
<div className="cookie-preferences-display">
<h3>Cookie Preferences</h3>
<div className="cookie-preferences-display__status">
<p>
<strong>Status:</strong> {state.hasConsented ? 'Consent Given' : 'No Consent'}
</p>
<p>
<strong>Functional Cookies:</strong> {state.preferences.functional ? 'Enabled' : 'Disabled'}
</p>
</div>
<div className="cookie-preferences-display__actions">
<button
type="button"
className="cookie-preferences-display__btn"
onClick={showSettings}
>
Update Preferences
</button>
<button
type="button"
className="cookie-preferences-display__btn cookie-preferences-display__btn--reset"
onClick={resetConsent}
>
Reset Consent
</button>
</div>
</div>
);
};

View File

@@ -0,0 +1,420 @@
'use client';
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
// Types for cookie consent
export interface CookiePreferences {
necessary: boolean;
functional: boolean;
}
export interface ConsentAuditLog {
timestamp: string;
action: 'consent_given' | 'consent_updated' | 'consent_withdrawn' | 'settings_opened';
preferences: CookiePreferences;
userAgent: string;
ipAddress?: string;
sessionId: string;
}
export interface CookieConsentConfig {
version: string;
companyName: string;
privacyPolicyUrl: string;
cookiePolicyUrl: string;
dataControllerEmail: string;
retentionPeriod: number; // days
enableAuditLog: boolean;
enableDetailedSettings: boolean;
showPrivacyNotice: boolean;
}
export interface CookieConsentState {
hasConsented: boolean;
preferences: CookiePreferences;
showBanner: boolean;
showSettings: boolean;
consentDate?: string;
lastUpdated?: string;
auditLog: ConsentAuditLog[];
}
export interface CookieConsentContextType {
state: CookieConsentState;
config: CookieConsentConfig;
acceptAll: () => void;
acceptNecessary: () => void;
acceptSelected: (preferences: Partial<CookiePreferences>) => void;
showSettings: () => void;
hideSettings: () => void;
updatePreferences: (preferences: Partial<CookiePreferences>) => void;
resetConsent: () => void;
withdrawConsent: () => void;
exportConsentData: () => string;
getConsentSummary: () => any;
}
// Default cookie preferences
const defaultPreferences: CookiePreferences = {
necessary: true, // Always true, cannot be disabled
functional: false,
};
// Enterprise configuration
const defaultConfig: CookieConsentConfig = {
version: '2.0',
companyName: 'Your Company Name',
privacyPolicyUrl: '/privacy-policy',
cookiePolicyUrl: '/cookie-policy',
dataControllerEmail: 'privacy@yourcompany.com',
retentionPeriod: 365, // 1 year
enableAuditLog: true,
enableDetailedSettings: true,
showPrivacyNotice: true,
};
// Default state
const defaultState: CookieConsentState = {
hasConsented: false,
preferences: defaultPreferences,
showBanner: false,
showSettings: false,
auditLog: [],
};
// Create context
const CookieConsentContext = createContext<CookieConsentContextType | undefined>(undefined);
// Storage keys
const CONSENT_STORAGE_KEY = 'cookie-consent-preferences';
const CONSENT_VERSION = '2.0';
// Utility functions
const generateSessionId = (): string => {
return Math.random().toString(36).substring(2) + Date.now().toString(36);
};
const createAuditLogEntry = (
action: ConsentAuditLog['action'],
preferences: CookiePreferences
): ConsentAuditLog => {
return {
timestamp: new Date().toISOString(),
action,
preferences,
userAgent: typeof window !== 'undefined' ? window.navigator.userAgent : '',
sessionId: generateSessionId(),
};
};
// Provider component
export const CookieConsentProvider: React.FC<{
children: ReactNode;
config?: Partial<CookieConsentConfig>;
}> = ({ children, config: customConfig }) => {
const [state, setState] = useState<CookieConsentState>(defaultState);
const config = { ...defaultConfig, ...customConfig };
// Load saved preferences on mount
useEffect(() => {
const loadSavedPreferences = () => {
try {
const saved = localStorage.getItem(CONSENT_STORAGE_KEY);
if (saved) {
const parsed = JSON.parse(saved);
// Check if saved version matches current version
if (parsed.version === CONSENT_VERSION) {
setState({
hasConsented: true,
preferences: parsed.preferences,
showBanner: false,
showSettings: false,
consentDate: parsed.consentDate,
lastUpdated: parsed.lastUpdated,
auditLog: parsed.auditLog || [],
});
return;
}
}
} catch (error) {
console.warn('Failed to load cookie preferences:', error);
}
// Show banner if no valid consent found
setState(prev => ({ ...prev, showBanner: true }));
};
loadSavedPreferences();
}, []);
// Save preferences to localStorage with audit logging
const savePreferences = (preferences: CookiePreferences, action: ConsentAuditLog['action'] = 'consent_given') => {
try {
const auditEntry = config.enableAuditLog ? createAuditLogEntry(action, preferences) : null;
const data = {
version: CONSENT_VERSION,
preferences,
timestamp: new Date().toISOString(),
consentDate: state.consentDate || new Date().toISOString(),
lastUpdated: new Date().toISOString(),
auditLog: auditEntry ? [...state.auditLog, auditEntry] : state.auditLog,
};
localStorage.setItem(CONSENT_STORAGE_KEY, JSON.stringify(data));
// Update state with audit log
if (auditEntry) {
setState(prev => ({
...prev,
auditLog: [...prev.auditLog, auditEntry],
}));
}
} catch (error) {
console.warn('Failed to save cookie preferences:', error);
}
};
// Accept all cookies
const acceptAll = () => {
const allAccepted: CookiePreferences = {
necessary: true,
functional: true,
};
setState(prev => ({
...prev,
hasConsented: true,
preferences: allAccepted,
showBanner: false,
showSettings: false,
consentDate: prev.consentDate || new Date().toISOString(),
lastUpdated: new Date().toISOString(),
}));
savePreferences(allAccepted, 'consent_given');
};
// Accept only necessary cookies
const acceptNecessary = () => {
const necessaryOnly: CookiePreferences = {
necessary: true,
functional: false,
};
setState(prev => ({
...prev,
hasConsented: true,
preferences: necessaryOnly,
showBanner: false,
showSettings: false,
consentDate: prev.consentDate || new Date().toISOString(),
lastUpdated: new Date().toISOString(),
}));
savePreferences(necessaryOnly, 'consent_given');
};
// Accept selected cookies
const acceptSelected = (preferences: Partial<CookiePreferences>) => {
const newPreferences: CookiePreferences = {
necessary: true, // Always true
functional: preferences.functional ?? false,
};
setState(prev => ({
...prev,
hasConsented: true,
preferences: newPreferences,
showBanner: false,
showSettings: false,
consentDate: prev.consentDate || new Date().toISOString(),
lastUpdated: new Date().toISOString(),
}));
savePreferences(newPreferences, 'consent_updated');
};
// Show settings modal
const showSettings = () => {
setState(prev => ({ ...prev, showSettings: true }));
// Log settings opened
if (config.enableAuditLog) {
const auditEntry = createAuditLogEntry('settings_opened', state.preferences);
setState(prev => ({
...prev,
auditLog: [...prev.auditLog, auditEntry],
}));
}
};
// Hide settings modal
const hideSettings = () => {
setState(prev => ({ ...prev, showSettings: false }));
};
// Update preferences (for settings modal)
const updatePreferences = (preferences: Partial<CookiePreferences>) => {
setState(prev => ({
...prev,
preferences: {
...prev.preferences,
...preferences,
necessary: true, // Always keep necessary as true
},
}));
};
// Reset consent (for testing or user request)
const resetConsent = () => {
try {
localStorage.removeItem(CONSENT_STORAGE_KEY);
} catch (error) {
console.warn('Failed to reset cookie preferences:', error);
}
setState({
hasConsented: false,
preferences: defaultPreferences,
showBanner: true,
showSettings: false,
auditLog: [],
});
};
// Withdraw consent (GDPR compliance)
const withdrawConsent = () => {
try {
localStorage.removeItem(CONSENT_STORAGE_KEY);
} catch (error) {
console.warn('Failed to withdraw consent:', error);
}
const auditEntry = config.enableAuditLog ? createAuditLogEntry('consent_withdrawn', defaultPreferences) : null;
setState({
hasConsented: false,
preferences: defaultPreferences,
showBanner: true,
showSettings: false,
auditLog: auditEntry ? [...state.auditLog, auditEntry] : state.auditLog,
});
};
// Export consent data (GDPR compliance)
const exportConsentData = (): string => {
const exportData = {
consentData: {
hasConsented: state.hasConsented,
preferences: state.preferences,
consentDate: state.consentDate,
lastUpdated: state.lastUpdated,
auditLog: state.auditLog,
},
config: {
version: config.version,
companyName: config.companyName,
retentionPeriod: config.retentionPeriod,
},
exportDate: new Date().toISOString(),
};
return JSON.stringify(exportData, null, 2);
};
// Get consent summary
const getConsentSummary = () => {
return {
hasConsented: state.hasConsented,
preferences: state.preferences,
consentDate: state.consentDate,
lastUpdated: state.lastUpdated,
auditLogCount: state.auditLog.length,
config: {
version: config.version,
companyName: config.companyName,
retentionPeriod: config.retentionPeriod,
},
};
};
const contextValue: CookieConsentContextType = {
state,
config,
acceptAll,
acceptNecessary,
acceptSelected,
showSettings,
hideSettings,
updatePreferences,
resetConsent,
withdrawConsent,
exportConsentData,
getConsentSummary,
};
return (
<CookieConsentContext.Provider value={contextValue}>
{children}
</CookieConsentContext.Provider>
);
};
// Hook to use cookie consent context
export const useCookieConsent = (): CookieConsentContextType => {
const context = useContext(CookieConsentContext);
if (context === undefined) {
throw new Error('useCookieConsent must be used within a CookieConsentProvider');
}
return context;
};
// Hook to check if specific cookie type is allowed
export const useCookiePermission = (type: keyof CookiePreferences): boolean => {
const { state } = useCookieConsent();
return state.preferences[type];
};
// Hook for functional features (only runs if functional cookies are allowed)
export const useFunctional = () => {
const { state } = useCookieConsent();
const isEnabled = state.preferences.functional && state.hasConsented;
const saveUserPreference = (key: string, value: any) => {
if (isEnabled && typeof window !== 'undefined') {
try {
localStorage.setItem(`user-preference-${key}`, JSON.stringify(value));
} catch (error) {
console.warn('Failed to save user preference:', error);
}
}
};
const loadUserPreference = (key: string, defaultValue?: any) => {
if (isEnabled && typeof window !== 'undefined') {
try {
const saved = localStorage.getItem(`user-preference-${key}`);
return saved ? JSON.parse(saved) : defaultValue;
} catch (error) {
console.warn('Failed to load user preference:', error);
return defaultValue;
}
}
return defaultValue;
};
const rememberUserAction = (action: string, data?: any) => {
if (isEnabled) {
console.log('User Action Remembered:', action, data);
// Implement your user action tracking logic here
}
};
return {
saveUserPreference,
loadUserPreference,
rememberUserAction,
isEnabled,
};
};

View File

@@ -0,0 +1,100 @@
'use client';
import React, { useEffect } from 'react';
import { useCookieConsent, useCookiePermission } from './CookieConsentContext';
// Utility hook for conditional rendering based on cookie permissions
export const useConditionalFeature = (featureType: 'functional') => {
const isAllowed = useCookiePermission(featureType);
const { state } = useCookieConsent();
return {
isAllowed,
hasConsented: state.hasConsented,
canShow: isAllowed && state.hasConsented,
};
};
// Note: Analytics and marketing hooks removed as we don't collect this data
// Hook for functional features (only runs if functional cookies are allowed)
export const useFunctional = () => {
const { canShow } = useConditionalFeature('functional');
const saveUserPreference = (key: string, value: any) => {
if (canShow && typeof window !== 'undefined') {
try {
localStorage.setItem(`user-preference-${key}`, JSON.stringify(value));
} catch (error) {
console.warn('Failed to save user preference:', error);
}
}
};
const loadUserPreference = (key: string, defaultValue?: any) => {
if (canShow && typeof window !== 'undefined') {
try {
const saved = localStorage.getItem(`user-preference-${key}`);
return saved ? JSON.parse(saved) : defaultValue;
} catch (error) {
console.warn('Failed to load user preference:', error);
return defaultValue;
}
}
return defaultValue;
};
const rememberUserAction = (action: string, data?: any) => {
if (canShow) {
console.log('User Action Remembered:', action, data);
// Implement your user action tracking logic here
}
};
return {
saveUserPreference,
loadUserPreference,
rememberUserAction,
isEnabled: canShow,
};
};
// Component wrapper for conditional rendering
interface ConditionalFeatureProps {
feature: 'functional';
children: React.ReactNode;
fallback?: React.ReactNode;
}
export const ConditionalFeature: React.FC<ConditionalFeatureProps> = ({
feature,
children,
fallback = null,
}) => {
const { canShow } = useConditionalFeature(feature);
return canShow ? <>{children}</> : <>{fallback}</>;
};
// Example usage components (analytics and marketing removed)
export const UserPreferenceManager: React.FC<{
preferenceKey: string;
defaultValue?: any;
children: (value: any, setValue: (value: any) => void) => React.ReactNode;
}> = ({ preferenceKey, defaultValue, children }) => {
const { saveUserPreference, loadUserPreference } = useFunctional();
const [value, setValue] = React.useState(defaultValue);
useEffect(() => {
const saved = loadUserPreference(preferenceKey, defaultValue);
setValue(saved);
}, [preferenceKey, defaultValue, loadUserPreference]);
const handleSetValue = (newValue: any) => {
setValue(newValue);
saveUserPreference(preferenceKey, newValue);
};
return <>{children(value, handleSetValue)}</>;
};

View File

@@ -0,0 +1,37 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
const AppearDown = () => {
useEffect(() => {
if (window.innerWidth >= 992) {
gsap.registerPlugin(ScrollTrigger);
const appearDownSections = document.querySelectorAll(".appear-down");
appearDownSections.forEach((section) => {
gsap.fromTo(
section,
{
scale: 0.8,
opacity: 0,
},
{
scale: 1,
opacity: 1,
duration: 1.5,
scrollTrigger: {
trigger: section,
scrub: 1,
start: "top bottom",
end: "bottom center",
markers: false,
},
}
);
});
}
}, []);
return null;
};
export default AppearDown;

View File

@@ -0,0 +1,45 @@
"use client";
import { useEffect } from "react";
const ButtonHoverAnimation = () => {
useEffect(() => {
const btnAnim = document.querySelectorAll(".btn-anim");
if (btnAnim.length > 0) {
btnAnim.forEach((element) => {
element.addEventListener("mouseenter", handleMouseEnter);
element.addEventListener("mouseleave", handleMouseLeave);
});
return () => {
btnAnim.forEach((element) => {
element.removeEventListener("mouseenter", handleMouseEnter);
element.removeEventListener("mouseleave", handleMouseLeave);
});
};
}
}, []);
const handleMouseEnter = (e: any) => {
const element = e.currentTarget as any;
const span = element.querySelector("span");
if (span) {
const rect = element.getBoundingClientRect();
span.style.left = `${e.clientX - rect.left}px`;
span.style.top = `${e.clientY - rect.top}px`;
}
};
const handleMouseLeave = (e: any) => {
const element = e.currentTarget as HTMLElement;
const span = element.querySelector("span");
if (span) {
const rect = element.getBoundingClientRect();
span.style.left = `${e.clientX - rect.left}px`;
span.style.top = `${e.clientY - rect.top}px`;
}
};
return null;
};
export default ButtonHoverAnimation;

View File

@@ -0,0 +1,122 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
const FadeAnimations = () => {
useEffect(() => {
if (window.innerWidth >= 992) {
gsap.registerPlugin(ScrollTrigger);
const fadeWrapperRefs = document.querySelectorAll(".fade-wrapper");
fadeWrapperRefs.forEach((fadeWrapperRef) => {
const fadeItems = fadeWrapperRef.querySelectorAll(".fade-top");
const fadeItemsBottom = fadeWrapperRef.querySelectorAll(".fade-bottom");
const fadeItemsLeft = fadeWrapperRef.querySelectorAll(".fade-left");
const fadeItemsRight = fadeWrapperRef.querySelectorAll(".fade-right");
// from top
fadeItems.forEach((element, index) => {
const delay = index * 0.15;
gsap.set(element, {
opacity: 0,
y: 100,
});
ScrollTrigger.create({
trigger: element,
start: "top 100%",
end: "bottom 20%",
scrub: 0.5,
onEnter: () => {
gsap.to(element, {
opacity: 1,
y: 0,
duration: 1,
delay: delay,
});
},
once: true,
});
});
// from bottom
fadeItemsBottom.forEach((element, index) => {
const delay = index * 0.15;
gsap.set(element, {
opacity: 0,
y: -100,
});
ScrollTrigger.create({
trigger: element,
start: "top 100%",
end: "bottom 20%",
scrub: 0.5,
onEnter: () => {
gsap.to(element, {
opacity: 1,
y: 0,
duration: 1,
delay: delay,
});
},
once: true,
});
});
// from left
fadeItemsLeft.forEach((element, index) => {
const delay = index * 0.15;
gsap.set(element, {
opacity: 0,
x: 100,
});
ScrollTrigger.create({
trigger: element,
start: "top 100%",
end: "bottom 20%",
scrub: 0.5,
onEnter: () => {
gsap.to(element, {
opacity: 1,
x: 0,
duration: 1,
delay: delay,
});
},
once: true,
});
});
// from right
fadeItemsRight.forEach((element, index) => {
const delay = index * 0.15;
gsap.set(element, {
opacity: 0,
x: -100,
});
ScrollTrigger.create({
trigger: element,
start: "top 100%",
end: "bottom 20%",
scrub: 0.5,
onEnter: () => {
gsap.to(element, {
opacity: 1,
x: 0,
duration: 1,
delay: delay,
});
},
once: true,
});
});
});
}
}, []);
return null;
};
export default FadeAnimations;

View File

@@ -0,0 +1,38 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
const FadeImageBottom = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
const deviceWidth = window.innerWidth;
if (
document.querySelectorAll(".fade-img").length > 0 &&
deviceWidth >= 992
) {
gsap.utils.toArray(".fade-img").forEach((el: any) => {
const tl = gsap.timeline({
scrollTrigger: {
trigger: el,
start: "center center",
end: "+=40%",
scrub: 1,
pin: false,
invalidateOnRefresh: true,
},
});
tl.to(el, {
y: "120px",
zIndex: "-1",
duration: 1,
});
});
}
}, []);
return null;
};
export default FadeImageBottom;

View File

@@ -0,0 +1,60 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
const ParallaxImage = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
const imageParallax = document.querySelectorAll(".parallax-image");
if (imageParallax.length > 0) {
imageParallax.forEach((element) => {
const animImageParallax = element as HTMLElement;
const aipWrap = animImageParallax.closest(
".parallax-image-wrap"
) as HTMLElement;
const aipInner = aipWrap?.querySelector(".parallax-image-inner");
if (aipWrap && aipInner) {
let tl_ImageParallax = gsap.timeline({
scrollTrigger: {
trigger: aipWrap,
start: "top bottom",
end: "bottom top",
scrub: true,
},
});
tl_ImageParallax.to(animImageParallax, {
yPercent: 30,
ease: "none",
});
gsap.fromTo(
aipInner,
{
scale: 1.2,
opacity: 0,
},
{
scale: 1,
opacity: 1,
duration: 1.5,
scrollTrigger: {
trigger: aipWrap,
start: "top 99%",
markers: false,
},
}
);
ScrollTrigger.refresh();
}
});
}
}, []);
return null;
};
export default ParallaxImage;

View File

@@ -0,0 +1,39 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { ScrollToPlugin } from "gsap/dist/ScrollToPlugin";
const ScrollToElement = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
const handleLinkClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
const target = e.currentTarget.getAttribute("href");
if (target) {
gsap.to(window, {
scrollTo: {
y: target,
offsetY: 200,
},
duration: 1.5,
ease: "power3.inOut",
});
}
};
const links = document.querySelectorAll('a[href^="#"]');
links.forEach((anchor: any) => {
anchor.addEventListener("click", handleLinkClick);
});
return () => {
links.forEach((anchor: any) => {
anchor.removeEventListener("click", handleLinkClick);
});
};
}, []);
return null;
};
export default ScrollToElement;

View File

@@ -0,0 +1,20 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import Lenis from "lenis";
const SmoothScroll = () => {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
const lenis = new Lenis();
gsap.ticker.add((time) => {
lenis.raf(time * 350);
});
gsap.ticker.lagSmoothing(0);
ScrollTrigger.update();
}, []);
return null;
};
export default SmoothScroll;

View File

@@ -0,0 +1,65 @@
"use client";
import { useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import SplitType from "split-type";
const SplitTextAnimations = () => {
useEffect(() => {
if (window.innerWidth >= 992) {
gsap.registerPlugin(ScrollTrigger);
new SplitType(".title-anim", {
types: ["chars", "words"],
});
const titleAnims = document.querySelectorAll(".title-anim");
titleAnims.forEach((titleAnim) => {
const charElements = titleAnim.querySelectorAll(".char");
charElements.forEach((char, index) => {
const tl2 = gsap.timeline({
scrollTrigger: {
trigger: char,
start: "top 90%",
end: "bottom 60%",
scrub: false,
markers: false,
toggleActions: "play none none none",
},
});
const charDelay = index * 0.03;
tl2.from(char, {
duration: 0.8,
x: 70,
delay: charDelay,
autoAlpha: 0,
});
});
});
const titleElements = document.querySelectorAll(".title-anim");
titleElements.forEach((el) => {
const triggerEl = el as gsap.DOMTarget;
gsap.to(triggerEl, {
scrollTrigger: {
trigger: triggerEl,
start: "top 100%",
markers: false,
onEnter: () => {
if (el instanceof Element) {
el.classList.add("title-anim-active");
}
},
},
});
});
}
}, []);
return null;
};
export default SplitTextAnimations;

View File

@@ -0,0 +1,33 @@
"use client";
import VanillaTilt from "vanilla-tilt";
const VanillaTiltHover = () => {
const tiltSelectors = [".btn-anim", ".topy-tilt"];
const tiltElements = document.querySelectorAll(tiltSelectors.join(", "));
tiltElements.forEach((element) => {
const tiltElement = element as HTMLElement;
let tiltConfig: any = {
speed: 3000,
};
if (tiltElement.classList.contains("btn-anim")) {
tiltConfig = {
...tiltConfig,
max: 15,
perspective: 400,
};
} else if (tiltElement.classList.contains("topy-tilt")) {
tiltConfig = {
...tiltConfig,
max: 5,
};
}
VanillaTilt.init(tiltElement, tiltConfig);
});
return null;
};
export default VanillaTiltHover;

View File

@@ -0,0 +1,290 @@
"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";
const Footer = () => {
const currentYear = new Date().getFullYear();
// Static header data
const headerData = {
title: "GNX Soft Ltd.",
logoUrl: "/images/logo.png",
logoLightUrl: "/images/logo-light.png",
navigationType: "both",
headerClass: "tp-header",
scrolledClass: "navbar-active",
buttonText: "Let's Talk",
buttonUrl: "/contact-us",
buttonClass: "btn btn-primary d-none d-sm-flex",
isActive: true,
displayOrder: 1,
metaData: JSON.stringify({
mobileBreakpoint: 992,
scrollThreshold: 50,
hideOnMobile: false,
mobileFirst: true,
hamburgerMenu: true
})
};
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;
return (
<footer className="footer position-relative overflow-x-clip">
<div className="container">
{/* Enterprise Footer Logo Section */}
<div className="row">
<div className="col-12">
<div className="footer-logo-section text-center pt-40 pb-30">
<div className="enterprise-logo-container">
<div className="enterprise-security-badges">
{/* Left Badge */}
<div className="security-badges-left">
<div className="security-badge">
<i className="fa-solid fa-building"></i>
<span>Enterprise Solutions</span>
</div>
</div>
{/* Center Logo */}
<div className="logo-center">
<Link href="/" aria-label="go to home" className="footer-logo">
<Image
src={logoSrc}
alt="Logo"
width={160}
height={120}
style={{
height: 'auto',
maxHeight: '120px'
}}
/>
</Link>
</div>
{/* Right Badge */}
<div className="security-badges-right">
<div className="security-badge">
<i className="fa-solid fa-shield-halved"></i>
<span>Incident Management</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="row vertical-column-gap-lg">
<div className="col-12">
<div className="pt-40">
</div>
</div>
</div>
<div className="row vertical-column-gap-lg pt-40">
<div className="col-12 col-lg-2 col-md-6">
<div className="footer-section">
<h6 className="text-white fm fw-6 mb-24">Company</h6>
<ul className="footer-links">
<li><Link href="about-us">About Us</Link></li>
<li><Link href="career">Careers</Link></li>
<li><Link href="case-study">Success Stories</Link></li>
<li><Link href="contact-us">Contact Us</Link></li>
</ul>
</div>
</div>
<div className="col-12 col-lg-2 col-md-6">
<div className="footer-section">
<h6 className="text-white fm fw-6 mb-24">Solutions</h6>
<ul className="footer-links">
<li><Link href="services">Incident Management Software</Link></li>
<li><Link href="services">Custom Software Development</Link></li>
<li><Link href="services">System Integrations & APIs</Link></li>
<li><Link href="services">Data Replication</Link></li>
</ul>
</div>
</div>
<div className="col-12 col-lg-2 col-md-6">
<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="case-study">Development Resources</Link></li>
<li><Link href="services">API Documentation</Link></li>
<li><Link href="contact-us">Technical Support</Link></li>
</ul>
</div>
</div>
<div className="col-12 col-lg-2 col-md-6">
<div className="footer-section">
<h6 className="text-white fm fw-6 mb-24">Services</h6>
<ul className="footer-links">
<li><Link href="services">Software Consulting</Link></li>
<li><Link href="contact-us">Custom Development</Link></li>
<li><Link href="case-study">API & Integration Services</Link></li>
<li><Link href="contact-us">Data Solutions</Link></li>
</ul>
</div>
</div>
<div className="col-12 col-lg-4 col-md-12">
<div className="footer-cta-section">
<div className="cta-content">
<h6 className="text-white fm fw-6 mb-24">Ready to Transform?</h6>
<p className="text-white mb-30">Start your software journey with our incident management and custom development solutions.</p>
<Link href="contact-us" className="btn-anim">
Start Your Software Journey
<i className="fa-solid fa-arrow-trend-up"></i>
<span></span>
</Link>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="footer__inner pt-60">
<div className="row vertical-column-gap-lg">
<div className="col-12 col-md-6 col-lg-4">
<div className="footer__inner-single">
<div className="thumb">
<Image src={location} alt="Image" width={24} height={24} />
</div>
<div className="content">
<h5 className="mt-8 fm fw-6 text-white mb-24">
Location
</h5>
<p className="text-quinary">
<Link
href="https://maps.google.com/?q=42.496781103070504,27.4758968970689"
target="_blank"
>
GNX Soft Ltd.<br />
Tsar Simeon I, 56<br />
Burgas, Burgas 8000<br />
Bulgaria
</Link>
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="footer__inner-single">
<div className="thumb">
<Image src={phone} alt="Image" width={24} height={24} />
</div>
<div className="content">
<h5 className="mt-8 fm fw-6 text-white mb-24">Phone</h5>
<p className="text-quinary mb-12">
<Link href="tel:+359897338147">+359 897 338 147</Link>
</p>
</div>
</div>
</div>
<div className="col-12 col-md-6 col-lg-4">
<div className="footer__inner-single">
<div className="thumb">
<Image src={gmail} alt="Image" width={24} height={24} />
</div>
<div className="content">
<h5 className="mt-8 fm fw-6 text-white mb-24">Email</h5>
<p className="text-quinary mb-12 text-lowercase">
<Link href="mailto:info@gnxsoft.com">
info@gnxsoft.com
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="footer-copyright">
<div className="row align-items-center vertical-column-gap">
<div className="col-12 col-lg-6">
<div className="footer__copyright-text text-center text-lg-start">
<p className="text-quinary mt-8">
&copy; <span id="copyrightYear">{currentYear}</span>{" "}
<Link href="/" className="fw-6">
GNX
</Link>
. All rights reserved. GNX Software Solutions.
</p>
</div>
</div>
<div className="col-12 col-lg-6">
<div className="social justify-content-center justify-content-lg-end">
<Link
href="https://www.linkedin.com/company/itify"
target="_blank"
title="LinkedIn"
>
<i className="fa-brands fa-linkedin"></i>
</Link>
<Link
href="https://github.com/itify"
target="_blank"
title="GitHub"
>
<i className="fa-brands fa-github"></i>
</Link>
<Link
href="https://www.twitter.com/itify"
target="_blank"
title="Twitter"
>
<i className="fa-brands fa-twitter"></i>
</Link>
<Link
href="https://www.youtube.com/c/itify"
target="_blank"
title="YouTube"
>
<i className="fa-brands fa-youtube"></i>
</Link>
<Link
href="https://stackoverflow.com/teams/itify"
target="_blank"
title="Stack Overflow"
>
<i className="fa-brands fa-stack-overflow"></i>
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</footer>
);
};
export default Footer;

View File

@@ -0,0 +1,267 @@
"use client";
import { useState, useEffect, useMemo } from "react";
import { usePathname } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import OffcanvasMenu from "./OffcanvasMenu";
import { OffcanvasData } from "@/public/data/offcanvas-data";
import { useNavigationServices } from "@/lib/hooks/useServices";
const Header = () => {
const [isOffcanvasOpen, setIsOffcanvasOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
const [isActive, setIsActive] = useState(true);
const [openDropdown, setOpenDropdown] = useState<number | null>(null);
const [isMobile, setIsMobile] = useState(false);
// Fetch services from API
const { services: apiServices, loading: servicesLoading, error: servicesError } = useNavigationServices();
// Create dynamic navigation data with services from API
const navigationData = useMemo(() => {
const baseNavigation = [...OffcanvasData];
// Find the Services menu item and update its submenu with API data
const servicesIndex = baseNavigation.findIndex(item => item.title === "Services");
if (servicesIndex !== -1 && apiServices.length > 0) {
console.log('Replacing services with API data:', apiServices);
baseNavigation[servicesIndex] = {
...baseNavigation[servicesIndex],
submenu: apiServices.map(service => ({
id: service.id + 1000, // Offset to avoid conflicts with existing IDs
title: service.title,
path: `/services/${service.slug}`,
parent_id: baseNavigation[servicesIndex].id,
display_order: service.display_order,
created_at: service.created_at,
updated_at: service.updated_at
}))
};
} else {
console.log('Using static services data. API services:', apiServices.length, 'Services index:', servicesIndex);
}
return baseNavigation;
}, [apiServices]);
// Static header data
const headerData = {
title: "EnterpriseSoft Solutions",
logoUrl: "/images/logo.png",
logoLightUrl: "/images/logo-light.png",
navigationType: "both",
headerClass: "tp-header",
scrolledClass: "navbar-active",
buttonText: "Get Started",
buttonUrl: "/contact-us",
buttonClass: "btn btn-primary d-none d-sm-flex",
isActive: true,
displayOrder: 1,
metaData: JSON.stringify({
mobileBreakpoint: 992,
scrollThreshold: 50,
hideOnMobile: false,
mobileFirst: true,
hamburgerMenu: true
})
};
const handleClick = () => {
setTimeout(() => {
setIsOffcanvasOpen(false);
}, 900);
setIsActive(false);
};
const handleDropdownToggle = (index: number) => {
setOpenDropdown(openDropdown === index ? null : index);
};
useEffect(() => {
const handleScroll = () => {
const scrollPosition = window.scrollY;
if (scrollPosition > 50) {
setScrolled(true);
} else {
setScrolled(false);
}
};
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [scrolled]);
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 992);
setTimeout(() => {
setIsOffcanvasOpen(false);
}, 900);
setIsActive(false);
};
handleResize(); // Check on mount
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
// Use static data
let logoSrc: string = headerData.logoUrl;
let headerClass = headerData.headerClass;
let buttonText = headerData.buttonText;
let buttonUrl = headerData.buttonUrl;
let buttonClass = headerData.buttonClass;
const pathname = usePathname();
// Override logo based on pathname if needed (maintain existing behavior)
if (
pathname === "/career" ||
pathname === "/" ||
pathname === "/index" ||
pathname === "/services" ||
pathname === "/service-single"
) {
logoSrc = headerData.logoLightUrl;
}
const handleOffCanvas = () => {
setIsOffcanvasOpen(true);
setIsActive(true);
};
return (
<>
<header className={headerClass}>
<div className={"primary-navbar" + (scrolled ? " navbar-active" : " ")}>
<div className="container">
<div className="row">
<div className="col-12">
<nav className="navbar p-0">
<div className="navbar__logo">
<Link href="/" aria-label="go to home" className="logo-img">
<Image
src={logoSrc}
alt="Logo"
width={160}
height={120}
style={{
height: 'auto'
}}
/>
</Link>
</div>
{/* Desktop Navigation Menu */}
<div className="navbar__menu d-none d-lg-flex">
<ul>
{navigationData.map((item, index) =>
item.submenu ? (
<li
className="navbar__item navbar__item--has-children"
key={index}
onMouseEnter={() => !isMobile && setOpenDropdown(index)}
onMouseLeave={() => !isMobile && setOpenDropdown(null)}
>
<button
aria-label="dropdown menu"
className={
"navbar__dropdown-label" +
(openDropdown === index
? " navbar__item-active"
: " ")
}
onClick={() => isMobile && handleDropdownToggle(index)}
>
{item.title}
{item.title === "Services" && servicesLoading && (
<span className="loading-indicator"></span>
)}
</button>
<ul className={`navbar__sub-menu ${openDropdown === index ? 'show' : ''}`}>
{item.title === "Services" && servicesLoading ? (
<li>
<span className="text-muted">Loading services...</span>
</li>
) : item.title === "Services" && servicesError ? (
<li>
<span className="text-danger">Failed to load services</span>
</li>
) : (
item.submenu.map((subItem, subIndex) => (
<li key={subIndex}>
<Link
href={subItem.path || "#"}
className={
pathname === subItem.path
? " active-current-sub"
: " "
}
>
{subItem.title}
</Link>
</li>
))
)}
</ul>
</li>
) : (
<li className="navbar__item" key={index}>
<Link
href={item.path || "#"}
className={
pathname === item.path ? " active-current-link" : " "
}
>
{item.title}
</Link>
</li>
)
)}
</ul>
</div>
<div className="navbar__options">
<Link href={buttonUrl} className={buttonClass}>
{buttonText}
</Link>
<button
className="open-offcanvas-nav d-lg-none"
aria-label="toggle mobile menu"
title="open offcanvas menu"
onClick={handleOffCanvas}
>
<span className="icon-bar top-bar"></span>
<span className="icon-bar middle-bar"></span>
<span className="icon-bar bottom-bar"></span>
</button>
</div>
</nav>
</div>
</div>
</div>
</div>
</header>
<OffcanvasMenu
isOffcanvasOpen={isOffcanvasOpen}
handleClick={handleClick}
isActive={isActive}
navigationData={navigationData}
servicesLoading={servicesLoading}
servicesError={servicesError}
/>
</>
);
};
export default Header;

View File

@@ -0,0 +1,215 @@
"use client";
import { useState, useEffect } from "react";
import { usePathname } from "next/navigation";
import AnimateHeight from "react-animate-height";
import Image from "next/legacy/image";
import Link from "next/link";
import { OffcanvasData } from "@/public/data/offcanvas-data";
import logoLight from "@/public/images/logo-light.png";
interface OffcanvasMenuProps {
isOffcanvasOpen: boolean;
isActive: boolean;
handleClick: () => void;
navigationData?: any[];
servicesLoading?: boolean;
servicesError?: string | null;
}
const OffcanvasMenu = ({
isOffcanvasOpen,
isActive,
handleClick,
navigationData = OffcanvasData,
servicesLoading = false,
servicesError = null
}: OffcanvasMenuProps) => {
const [openDropdown, setOpenDropdown] = useState(null);
const handleDropdownToggle = (index: any) => {
setOpenDropdown((prev) => (prev === index ? null : index));
};
const pathname = usePathname();
useEffect(() => {
const parentItems = document.querySelectorAll(
".navbar__item--has-children"
);
parentItems.forEach((parentItem) => {
const childItems = parentItem.querySelectorAll(".active-current-sub");
if (childItems.length > 0) {
parentItem.classList.add("active-current-parent");
}
});
}, []);
return (
<div className="offcanvas-nav">
<div
className={
"offcanvas-menu" + (isOffcanvasOpen ? " show-offcanvas-menu" : " ")
}
>
<nav
className={
"offcanvas-menu__wrapper" + (isActive ? " " : " nav-fade-active")
}
data-lenis-prevent
>
<div className="offcanvas-menu__header nav-fade">
<div className="logo">
<Link href="/" className="logo-img">
<Image src={logoLight} priority alt="Image" title="Logo" width={160} height={60} />
</Link>
</div>
<button
aria-label="close offcanvas menu"
className="close-offcanvas-menu"
onClick={handleClick}
>
<i className="fa-solid fa-xmark"></i>
</button>
</div>
<div className="offcanvas-menu__list">
<div className="navbar__menu">
<ul>
{navigationData.map((item, index) =>
item.submenu ? (
<li
className="navbar__item navbar__item--has-children nav-fade"
key={index}
>
<button
aria-label="dropdown menu"
className={
"navbar__dropdown-label" +
(openDropdown === index
? " navbar__item-active"
: " ")
}
onClick={() => handleDropdownToggle(index)}
>
{item.title}
{item.title === "Services" && servicesLoading && (
<span className="loading-indicator"></span>
)}
</button>
<AnimateHeight
duration={400}
height={openDropdown === index ? "auto" : 0}
>
<ul className="navbar__sub-menu">
{item.title === "Services" && servicesLoading ? (
<li>
<span className="text-muted">Loading services...</span>
</li>
) : item.title === "Services" && servicesError ? (
<li>
<span className="text-danger">Failed to load services</span>
</li>
) : (
item.submenu.map((subItem, subIndex) => (
<li key={subIndex}>
<Link
href={subItem.path || "#"}
className={
pathname === subItem.path
? " active-current-sub"
: " "
}
>
{subItem.title}
</Link>
</li>
))
)}
</ul>
</AnimateHeight>
</li>
) : (
<li className="navbar__item nav-fade" key={index}>
<Link
href={item.path || "#"}
className={
pathname === item.path ? " active-current-link" : " "
}
>
{item.title}
</Link>
</li>
)
)}
</ul>
</div>
</div>
</nav>
<div className="offcanvas-menu__enterprise-info nav-fade">
<div className="enterprise-contact">
<h4>Get in Touch</h4>
<p>Ready to transform your business?</p>
<div className="contact-methods">
<a href="tel:+1-800-ENTERPRISE" className="contact-item">
<i className="fa-solid fa-phone"></i>
<span>+1 (800) ENTERPRISE</span>
</a>
<a href="mailto:solutions@enterprise.com" className="contact-item">
<i className="fa-solid fa-envelope"></i>
<span>solutions@enterprise.com</span>
</a>
</div>
</div>
</div>
<ul className="enterprise-social nav-fade">
<li>
<Link
href="https://www.linkedin.com/company/enterprise"
target="_blank"
aria-label="Connect with us on LinkedIn"
>
<i className="fa-brands fa-linkedin-in"></i>
</Link>
</li>
<li>
<Link
href="https://www.twitter.com/enterprise"
target="_blank"
aria-label="Follow us on Twitter"
>
<i className="fa-brands fa-twitter"></i>
</Link>
</li>
<li>
<Link
href="https://www.youtube.com/enterprise"
target="_blank"
aria-label="Watch our videos on YouTube"
>
<i className="fa-brands fa-youtube"></i>
</Link>
</li>
<li>
<Link
href="https://github.com/enterprise"
target="_blank"
aria-label="View our code on GitHub"
>
<i className="fa-brands fa-github"></i>
</Link>
</li>
</ul>
<div className="anime">
<span className="nav-fade"></span>
<span className="nav-fade"></span>
<span className="nav-fade"></span>
<span className="nav-fade"></span>
<span className="nav-fade"></span>
<span className="nav-fade"></span>
</div>
</div>
</div>
);
};
export default OffcanvasMenu;