enhance loader design

This commit is contained in:
Mohammed Al-yaseen
2025-08-02 02:25:27 +03:00
parent e627594be9
commit e6a3bd1fd5
7 changed files with 514 additions and 540 deletions

View File

@@ -1,185 +0,0 @@
// File: src/components/home/ServicesSection.tsx
"use client";
import {
CloudOutlined,
CodeOutlined,
GlobalOutlined,
LineChartOutlined,
MobileOutlined,
RobotOutlined,
RocketOutlined,
ShoppingOutlined,
} from '@ant-design/icons';
import { Button, Card, Col, Row, Typography } from 'antd';
import { motion } from 'framer-motion';
import React, { useEffect, useState } from 'react';
import styles from './ServicesSelector.module.css';
const { Title, Paragraph } = Typography;
interface ServicesSectionProps {
userPreferences: string[];
}
interface Service {
id: string;
title: string;
description: string;
icon: React.ReactNode;
preferenceMatches: string[];
}
const allServices: Service[] = [
{
id: 'webdev',
title: 'Web Development',
description: 'Custom web applications with cutting-edge technologies and responsive design.',
icon: <CodeOutlined className={styles.serviceIcon} />,
preferenceMatches: ['ecommerce', 'cloud', 'seo']
},
{
id: 'branding',
title: 'Branding & Identity',
description: 'Complete brand identity packages including logos, guidelines, and visual systems.',
icon: <RocketOutlined className={styles.serviceIcon} />,
preferenceMatches: ['branding', 'seo']
},
{
id: 'ecom',
title: 'E-commerce Solutions',
description: 'Full-stack e-commerce platforms with secure payment integration and inventory management.',
icon: <ShoppingOutlined className={styles.serviceIcon} />,
preferenceMatches: ['ecommerce', 'branding']
},
{
id: 'seo',
title: 'SEO & Marketing',
description: 'Data-driven digital marketing strategies to improve visibility and drive conversions.',
icon: <LineChartOutlined className={styles.serviceIcon} />,
preferenceMatches: ['seo', 'branding']
},
{
id: 'mobile',
title: 'Mobile Development',
description: 'Native and cross-platform mobile applications for iOS and Android.',
icon: <MobileOutlined className={styles.serviceIcon} />,
preferenceMatches: ['mobile', 'ai']
},
{
id: 'cloud',
title: 'Cloud Solutions',
description: 'Scalable cloud infrastructures, migrations, and DevOps automation.',
icon: <CloudOutlined className={styles.serviceIcon} />,
preferenceMatches: ['cloud', 'ai']
},
{
id: 'ai',
title: 'AI & Machine Learning',
description: 'Custom AI solutions for automation, prediction, and data analysis.',
icon: <RobotOutlined className={styles.serviceIcon} />,
preferenceMatches: ['ai', 'cloud']
},
{
id: 'global',
title: 'Global IT Consulting',
description: 'Strategic technology consulting to drive digital transformation and innovation.',
icon: <GlobalOutlined className={styles.serviceIcon} />,
preferenceMatches: ['cloud', 'branding', 'seo']
},
];
const ServicesSection: React.FC<ServicesSectionProps> = ({ userPreferences }) => {
const [services, setServices] = useState<Service[]>([]);
useEffect(() => {
// Sort services based on user preferences
if (userPreferences.length > 0) {
const sortedServices = [...allServices].sort((a, b) => {
const aMatches = a.preferenceMatches.filter(pref => userPreferences.includes(pref)).length;
const bMatches = b.preferenceMatches.filter(pref => userPreferences.includes(pref)).length;
return bMatches - aMatches;
});
setServices(sortedServices);
} else {
// If no preferences, show all services in default order
setServices(allServices);
}
}, [userPreferences]);
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1
}
}
};
const itemVariants = {
hidden: { y: 50, opacity: 0 },
visible: {
y: 0,
opacity: 1,
transition: { duration: 0.5 }
}
};
return (
<section className={styles.servicesSection}>
<div className={styles.sectionBackground}>
<div className={styles.glowOrb}></div>
</div>
<div className={styles.container}>
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className={styles.sectionHeader}
>
<Title level={2} className={styles.sectionTitle}>Our Services</Title>
<Paragraph className={styles.sectionSubtitle}>
Innovative technology solutions customized for your business needs
</Paragraph>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<Row gutter={[24, 24]}>
{services.map((service) => (
<Col xs={24} sm={12} lg={8} xl={6} key={service.id}>
<motion.div variants={itemVariants}>
<Card
hoverable
className={styles.serviceCard}
cover={
<div className={styles.serviceIconWrapper}>
{service.icon}
</div>
}
>
<Card.Meta
title={service.title}
description={service.description}
/>
<Button type="link" className={styles.learnMoreBtn}>
Learn more
</Button>
</Card>
</motion.div>
</Col>
))}
</Row>
</motion.div>
</div>
</section>
);
};
export default ServicesSection;

View File

@@ -1,102 +0,0 @@
/* File: src/components/home/ServicesSection.module.css */
.servicesSection {
position: relative;
padding: 100px 0;
overflow: hidden;
background-color: #f8f9fa;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 16px;
position: relative;
z-index: 2;
}
.sectionBackground {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 1;
}
.glowOrb {
position: absolute;
width: 500px;
height: 500px;
border-radius: 50%;
background: var(--primary-glow);
top: -150px;
right: -100px;
filter: blur(50px);
}
.sectionHeader {
text-align: center;
margin-bottom: 60px;
}
.sectionTitle {
font-size: 2.5rem !important;
font-weight: 700 !important;
margin-bottom: 16px !important;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.sectionSubtitle {
font-size: 1.1rem;
color: #666;
max-width: 600px;
margin: 0 auto;
}
.serviceCard {
height: 100%;
border-radius: 12px;
overflow: hidden;
transition: all 0.3s ease;
border: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.serviceCard:hover {
transform: translateY(-8px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}
.serviceIconWrapper {
display: flex;
justify-content: center;
align-items: center;
height: 120px;
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7eb 100%);
}
.serviceIcon {
font-size: 3rem;
color: #6e48aa;
}
.learnMoreBtn {
display: block;
margin-top: 16px;
padding: 0;
font-weight: 500;
}
@media (max-width: 768px) {
.servicesSection {
padding: 60px 0;
}
.sectionTitle {
font-size: 2rem !important;
}
}

View File

@@ -10,23 +10,217 @@
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #42475C 0%, #20222F 100%);
background: linear-gradient(135deg, #0F0525 0%, #1a0b3a 50%, #2A0B45 100%);
position: relative;
overflow: hidden;
}
.loaderBackground {
position: absolute;
inset: 0;
overflow: hidden;
}
.loaderOrb1 {
position: absolute;
top: -200px;
left: -200px;
width: 400px;
height: 400px;
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
border-radius: 50%;
filter: blur(60px);
animation: float 8s ease-in-out infinite;
opacity: 0.3;
}
.loaderOrb2 {
position: absolute;
top: 50%;
right: -150px;
width: 300px;
height: 300px;
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
border-radius: 50%;
filter: blur(50px);
animation: float 6s ease-in-out infinite reverse;
opacity: 0.2;
}
.loaderOrb3 {
position: absolute;
bottom: -100px;
left: 50%;
width: 250px;
height: 250px;
background: linear-gradient(135deg, #ec4899 0%, #f97316 100%);
border-radius: 50%;
filter: blur(40px);
animation: float 10s ease-in-out infinite;
opacity: 0.25;
}
@keyframes float {
0%, 100% {
transform: translateY(0px) rotate(0deg);
}
50% {
transform: translateY(-30px) rotate(180deg);
}
}
.loaderContent {
position: relative;
z-index: 10;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 40px;
}
.logoContainer {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.logoIcon {
width: 80px;
height: 80px;
border-radius: 20px;
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
display: flex;
align-items: center;
justify-content: center;
position: relative;
animation: logoPulse 2s ease-in-out infinite;
}
.logoInner {
width: 40px;
height: 40px;
border-radius: 10px;
background: white;
animation: logoRotate 3s linear infinite;
}
@keyframes logoPulse {
0%, 100% {
transform: scale(1);
box-shadow: 0 0 30px rgba(139, 92, 246, 0.5);
}
50% {
transform: scale(1.05);
box-shadow: 0 0 50px rgba(139, 92, 246, 0.8);
}
}
@keyframes logoRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.logoText {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.logoTitle {
font-size: 2rem;
font-weight: 700;
color: white;
letter-spacing: 2px;
}
.logoSubtitle {
font-size: 1.2rem;
font-weight: 500;
color: #a855f7;
letter-spacing: 1px;
}
.loaderAnimation {
display: flex;
justify-content: center;
align-items: center;
}
.loaderDots {
display: flex;
gap: 8px;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
animation: dotBounce 1.4s ease-in-out infinite both;
}
.dot:nth-child(1) {
animation-delay: -0.32s;
}
.dot:nth-child(2) {
animation-delay: -0.16s;
}
.dot:nth-child(3) {
animation-delay: 0s;
}
@keyframes dotBounce {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
.loaderText {
margin-top: 20px;
color: white;
opacity: 0.8;
animation: pulse 2s infinite;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
@keyframes pulse {
0% { opacity: 0.6; }
50% { opacity: 1; }
100% { opacity: 0.6; }
.loaderTitle {
color: white !important;
font-size: 1.5rem !important;
font-weight: 600 !important;
margin: 0 !important;
animation: textFade 2s ease-in-out infinite;
}
.loaderSubtitle {
color: #cbd5e1;
font-size: 0.95rem;
margin: 0;
opacity: 0.8;
animation: textFade 2s ease-in-out infinite 0.5s;
}
@keyframes textFade {
0%, 100% {
opacity: 0.7;
}
50% {
opacity: 1;
}
}
.section {
@@ -39,4 +233,76 @@
.section {
padding: 60px 16px;
}
.loaderContent {
gap: 30px;
}
.logoIcon {
width: 70px;
height: 70px;
}
.logoInner {
width: 35px;
height: 35px;
}
.logoTitle {
font-size: 1.8rem;
}
.logoSubtitle {
font-size: 1.1rem;
}
.loaderTitle {
font-size: 1.3rem !important;
}
.loaderSubtitle {
font-size: 0.9rem;
}
.dot {
width: 10px;
height: 10px;
}
}
@media (max-width: 480px) {
.loaderContent {
gap: 25px;
}
.logoIcon {
width: 60px;
height: 60px;
}
.logoInner {
width: 30px;
height: 30px;
}
.logoTitle {
font-size: 1.6rem;
}
.logoSubtitle {
font-size: 1rem;
}
.loaderTitle {
font-size: 1.2rem !important;
}
.loaderSubtitle {
font-size: 0.85rem;
}
.dot {
width: 8px;
height: 8px;
}
}

View File

@@ -1,13 +1,12 @@
// File: src/pages/index.tsx
"use client";
import { Spin, Typography } from "antd";
import { Typography } from "antd";
import { useEffect, useState } from "react";
import Footer from "./components/Footer/Footer";
import HeroSection from "./components/Hero/HeroSection";
import PreferencesSelector from "./components/Preferences/Preferences";
import ProjectsShowcase from "./components/ProjectsShowcase/ProjectsShowcase";
import ServicesSection from "./components/Services/Services";
import TestimonialsSection from "./components/Testimonials/Testimonials";
import styles from "./page.module.css";
@@ -17,6 +16,8 @@ export default function Home() {
const [showPreferences, setShowPreferences] = useState(true);
const [loading, setLoading] = useState(true);
const [userPreferences, setUserPreferences] = useState<string[]>([]);
console.log(userPreferences);
useEffect(() => {
// Check if preferences already exist in localStorage
@@ -46,10 +47,40 @@ export default function Home() {
if (loading) {
return (
<div className={styles.loaderContainer}>
<Spin size="large" />
<Title level={4} className={styles.loaderText}>
Preparing Tech Master Experience...
<div className={styles.loaderBackground}>
<div className={styles.loaderOrb1}></div>
<div className={styles.loaderOrb2}></div>
<div className={styles.loaderOrb3}></div>
</div>
<div className={styles.loaderContent}>
<div className={styles.logoContainer}>
<div className={styles.logoIcon}>
<div className={styles.logoInner}></div>
</div>
<div className={styles.logoText}>
<span className={styles.logoTitle}>Tech</span>
<span className={styles.logoSubtitle}>Masters</span>
</div>
</div>
<div className={styles.loaderAnimation}>
<div className={styles.loaderDots}>
<div className={styles.dot}></div>
<div className={styles.dot}></div>
<div className={styles.dot}></div>
</div>
</div>
<div className={styles.loaderText}>
<Title level={4} className={styles.loaderTitle}>
Preparing Your Experience
</Title>
<p className={styles.loaderSubtitle}>
Loading innovative solutions and cutting-edge technology
</p>
</div>
</div>
</div>
);
}
@@ -65,10 +96,6 @@ export default function Home() {
<HeroSection />
</section>
<section id="services">
<ServicesSection userPreferences={userPreferences} />
</section>
<section id="projects">
<ProjectsShowcase />
</section>

View File

@@ -289,7 +289,7 @@ export default function ProjectsPage() {
const [selectedCategory, setSelectedCategory] = useState("All");
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
const [isModalVisible, setIsModalVisible] = useState(false);
const [visibleProjects, setVisibleProjects] = useState(6);
const [visibleProjects, setVisibleProjects] = useState(9);
const filteredProjects =
selectedCategory === "All"
@@ -318,11 +318,14 @@ export default function ProjectsPage() {
if (selectedCategory === category) {
// If clicking on the same category, remove the filter
setSelectedCategory("All");
// When showing all projects, show more initially
setVisibleProjects(9);
} else {
// Otherwise, set the new category
setSelectedCategory(category);
}
// When filtering, show fewer projects initially
setVisibleProjects(6);
}
};
const containerVariants = {

View File

@@ -264,13 +264,14 @@
/* Service Cards */
.serviceCard {
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border-radius: 24px;
padding: 0;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
border: none;
height: 100%;
}
.serviceCard::before {
@@ -281,26 +282,52 @@
right: 0;
height: 4px;
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
transform: scaleX(0);
transition: transform 0.3s ease;
}
.serviceCard:hover::before {
transform: scaleX(1);
}
.serviceCard:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(139, 92, 246, 0.15);
}
.cardHeader {
padding: 32px 32px 24px;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
position: relative;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.serviceIconWrapper {
width: 80px;
height: 80px;
border-radius: 20px;
width: 70px;
height: 70px;
border-radius: 18px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 24px;
transition: all 0.3s ease;
position: relative;
z-index: 1;
}
.serviceCard:hover .serviceIconWrapper {
transform: scale(1.1);
transform: scale(1.1) rotate(5deg);
}
.serviceBadge {
background: rgba(139, 92, 246, 0.1);
color: #8b5cf6;
padding: 6px 12px;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
border: 1px solid rgba(139, 92, 246, 0.2);
}
.serviceIcon {
@@ -341,8 +368,12 @@
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
}
.cardContent {
padding: 0 32px 32px;
}
.serviceTitle {
font-size: 1.5rem;
font-size: 1.4rem;
font-weight: 700;
color: #1e293b;
margin-bottom: 12px;
@@ -352,43 +383,66 @@
.serviceDescription {
color: #64748b;
line-height: 1.6;
margin-bottom: 20px;
margin-bottom: 24px;
font-size: 0.95rem;
}
.featuresContainer {
margin-bottom: 24px;
}
.featuresTitle {
font-size: 0.9rem;
font-weight: 600;
color: #475569;
margin-bottom: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.serviceFeatures {
list-style: none;
padding: 0;
margin: 0 0 24px 0;
margin: 0;
}
.serviceFeature {
display: flex;
align-items: center;
gap: 8px;
gap: 10px;
color: #64748b;
font-size: 0.9rem;
margin-bottom: 8px;
margin-bottom: 10px;
padding: 8px 0;
}
.serviceFeature::before {
content: '✓';
color: #10b981;
font-weight: bold;
.featureIcon {
color: #8b5cf6;
font-size: 0.8rem;
font-weight: bold;
}
.cardFooter {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20px;
border-top: 1px solid #f1f5f9;
}
.learnMoreBtn {
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
border: none;
color: white;
padding: 12px 24px;
border-radius: 25px;
padding: 10px 20px;
border-radius: 20px;
font-weight: 600;
font-size: 0.9rem;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 8px;
gap: 6px;
height: auto;
}
.learnMoreBtn:hover {
@@ -398,6 +452,23 @@
color: white;
}
.serviceStats {
display: flex;
flex-direction: column;
gap: 4px;
text-align: right;
}
.serviceStats .statItem {
font-size: 0.75rem;
color: #64748b;
line-height: 1.2;
}
.serviceStats .statItem strong {
color: #8b5cf6;
}
/* Process Section */
.processSection {
padding: 80px 0;
@@ -597,7 +668,28 @@
}
.serviceCard {
padding: 30px 20px;
margin: 0 10px;
}
.cardHeader {
padding: 24px 20px 20px;
}
.cardContent {
padding: 0 20px 24px;
}
.cardFooter {
flex-direction: column;
gap: 16px;
align-items: stretch;
}
.serviceStats {
text-align: center;
flex-direction: row;
justify-content: center;
gap: 20px;
}
.processSteps {
@@ -616,7 +708,24 @@
}
.serviceCard {
padding: 25px 15px;
margin: 0 5px;
}
.cardHeader {
padding: 20px 16px 16px;
}
.cardContent {
padding: 0 16px 20px;
}
.serviceIconWrapper {
width: 60px;
height: 60px;
}
.serviceIcon {
font-size: 24px;
}
.servicesTitle,

View File

@@ -2,31 +2,21 @@
import {
ArrowRightOutlined,
BulbOutlined,
CloudOutlined,
CodeOutlined,
EnvironmentOutlined,
FacebookOutlined,
GlobalOutlined,
InstagramOutlined,
LineChartOutlined,
LinkedinOutlined,
MailOutlined,
MobileOutlined,
PhoneOutlined,
RobotOutlined,
RocketOutlined,
ShoppingOutlined,
TeamOutlined,
TrophyOutlined,
TwitterOutlined,
ShoppingOutlined
} from "@ant-design/icons";
import { Button, Card, Typography } from "antd";
import { Button, Typography } from "antd";
import { motion } from "framer-motion";
import React, { useEffect, useState } from "react";
import styles from "./page.module.css";
const { Title, Paragraph, Text } = Typography;
const { Title, Paragraph } = Typography;
interface Service {
id: string;
@@ -255,174 +245,6 @@ export default function ServicesPage() {
</div>
</motion.div>
</div>
{/* Hero Footer */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
className={styles.heroFooter}
>
<div className={styles.heroFooterContent}>
<div className={styles.footerColumn}>
<div className={styles.footerColumnTitle}>
<TeamOutlined className={styles.footerColumnIcon} />
Company
</div>
<ul className={styles.footerLinks}>
<li className={styles.footerLink}>
<a href="/about">
<ArrowRightOutlined className={styles.footerLinkIcon} />
About Us
</a>
</li>
<li className={styles.footerLink}>
<a href="/services">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Our Services
</a>
</li>
<li className={styles.footerLink}>
<a href="/projects">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Portfolio
</a>
</li>
<li className={styles.footerLink}>
<a href="/contact">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Contact Us
</a>
</li>
</ul>
</div>
<div className={styles.footerColumn}>
<div className={styles.footerColumnTitle}>
<BulbOutlined className={styles.footerColumnIcon} />
Services
</div>
<ul className={styles.footerLinks}>
<li className={styles.footerLink}>
<a href="/services#webdev">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Web Development
</a>
</li>
<li className={styles.footerLink}>
<a href="/services#mobile">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Mobile Apps
</a>
</li>
<li className={styles.footerLink}>
<a href="/services#ai">
<ArrowRightOutlined className={styles.footerLinkIcon} />
AI Solutions
</a>
</li>
<li className={styles.footerLink}>
<a href="/services#cloud">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Cloud Services
</a>
</li>
</ul>
</div>
<div className={styles.footerColumn}>
<div className={styles.footerColumnTitle}>
<TrophyOutlined className={styles.footerColumnIcon} />
Resources
</div>
<ul className={styles.footerLinks}>
<li className={styles.footerLink}>
<a href="/blog">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Blog & Insights
</a>
</li>
<li className={styles.footerLink}>
<a href="/case-studies">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Case Studies
</a>
</li>
<li className={styles.footerLink}>
<a href="/whitepapers">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Whitepapers
</a>
</li>
<li className={styles.footerLink}>
<a href="/webinars">
<ArrowRightOutlined className={styles.footerLinkIcon} />
Webinars
</a>
</li>
</ul>
</div>
<div className={styles.footerColumn}>
<div className={styles.footerColumnTitle}>
<MailOutlined className={styles.footerColumnIcon} />
Contact Info
</div>
<ul className={styles.footerLinks}>
<li className={styles.footerLink}>
<a href="mailto:info@techmaster.com">
<MailOutlined className={styles.footerLinkIcon} />
info@techmaster.com
</a>
</li>
<li className={styles.footerLink}>
<a href="tel:+15551234567">
<PhoneOutlined className={styles.footerLinkIcon} />
+1 (555) 123-4567
</a>
</li>
<li className={styles.footerLink}>
<a href="#">
<EnvironmentOutlined className={styles.footerLinkIcon} />
San Francisco, CA
</a>
</li>
<li className={styles.footerLink}>
<a href="/support">
<ArrowRightOutlined className={styles.footerLinkIcon} />
24/7 Support
</a>
</li>
</ul>
</div>
</div>
<div className={styles.footerBottom}>
<Paragraph className={styles.footerBottomText}>
Ready to transform your business? Let's discuss your next project.
</Paragraph>
<div className={styles.socialLinks}>
<a href="#" className={styles.socialLink}>
<FacebookOutlined />
</a>
<a href="#" className={styles.socialLink}>
<TwitterOutlined />
</a>
<a href="#" className={styles.socialLink}>
<LinkedinOutlined />
</a>
<a href="#" className={styles.socialLink}>
<InstagramOutlined />
</a>
</div>
<div className={styles.copyright}>
© 2024 Tech Master. All rights reserved. | Privacy Policy | Terms
of Service
</div>
</div>
</motion.div>
</section>
{/* Services Section */}
@@ -453,15 +275,28 @@ export default function ServicesPage() {
viewport={{ once: true }}
className={styles.servicesGrid}
>
{services.map((service) => (
<motion.div key={service.id} variants={itemVariants}>
<Card className={styles.serviceCard}>
{services.map((service, index) => (
<motion.div
key={service.id}
variants={itemVariants}
whileHover={{
scale: 1.02,
transition: { duration: 0.2 }
}}
>
<div className={styles.serviceCard}>
<div className={styles.cardHeader}>
<div
className={`${styles.serviceIconWrapper} ${service.iconClass}`}
>
{service.icon}
</div>
<div className={styles.serviceBadge}>
Service {String(index + 1).padStart(2, '0')}
</div>
</div>
<div className={styles.cardContent}>
<Title level={3} className={styles.serviceTitle}>
{service.title}
</Title>
@@ -470,18 +305,39 @@ export default function ServicesPage() {
{service.description}
</Paragraph>
<div className={styles.featuresContainer}>
<h4 className={styles.featuresTitle}>Key Features</h4>
<ul className={styles.serviceFeatures}>
{service.features.map((feature, index) => (
<li key={index} className={styles.serviceFeature}>
<motion.li
key={index}
className={styles.serviceFeature}
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
>
<span className={styles.featureIcon}></span>
{feature}
</li>
</motion.li>
))}
</ul>
</div>
<Button type="link" className={styles.learnMoreBtn}>
Learn More <ArrowRightOutlined />
<div className={styles.cardFooter}>
<Button type="primary" className={styles.learnMoreBtn}>
Explore Service <ArrowRightOutlined />
</Button>
</Card>
<div className={styles.serviceStats}>
<span className={styles.statItem}>
<strong>24/7</strong> Support
</span>
<span className={styles.statItem}>
<strong>100%</strong> Satisfaction
</span>
</div>
</div>
</div>
</div>
</motion.div>
))}
</motion.div>
@@ -546,7 +402,7 @@ export default function ServicesPage() {
<span className={styles.gradientText}>Project</span>?
</Title>
<Paragraph className={styles.ctaSubtitle}>
Let's discuss how we can help bring your vision to life. Our team
Let&apos;s discuss how we can help bring your vision to life. Our team
is ready to create something amazing together.
</Paragraph>
<Button size="large" className={styles.ctaButton}>