Compare commits
10 Commits
9271f776d7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3bc52d60c3 | |||
|
|
5f050a7a60 | ||
|
|
7bcbea35e1 | ||
|
|
e6a3bd1fd5 | ||
|
|
e627594be9 | ||
|
|
01ed3a2b7f | ||
|
|
b803532cde | ||
|
|
e32ddaa2db | ||
|
|
b2896c379f | ||
|
|
c9998ce4e0 |
@@ -1,16 +1,6 @@
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import coreWebVitals from "eslint-config-next/core-web-vitals";
|
||||
import typescript from "eslint-config-next/typescript";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const config = [...coreWebVitals, ...typescript];
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
});
|
||||
|
||||
const eslintConfig = [
|
||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||
];
|
||||
|
||||
export default eslintConfig;
|
||||
export default config;
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "techmasters.space",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
29
package.json
29
package.json
@@ -2,26 +2,27 @@
|
||||
"name": "antd-demo",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"start": "next start -p 4000",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"antd": "^5.24.6",
|
||||
"framer-motion": "^12.6.3",
|
||||
"next": "15.2.4",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
"antd": "^6.1.1",
|
||||
"framer-motion": "^12.23.26",
|
||||
"next": "16.0.10",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "15.2.4",
|
||||
"typescript": "^5"
|
||||
"@eslint/eslintrc": "^3.3.3",
|
||||
"@types/node": "^20.19.27",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-next": "16.0.10",
|
||||
"typescript": "5.8.3"
|
||||
}
|
||||
}
|
||||
|
||||
32
src/app/about/layout.tsx
Normal file
32
src/app/about/layout.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "About Us | Tech Master - Award-Winning IT Solutions Dubai",
|
||||
description: "Learn about Tech Master, an award-winning Dubai-based technology agency specializing in digital transformation, web development, and innovative IT solutions since 2020.",
|
||||
keywords: [
|
||||
"about Tech Master",
|
||||
"Dubai IT company",
|
||||
"award-winning tech agency",
|
||||
"digital transformation company",
|
||||
"web development company Dubai",
|
||||
"IT solutions provider",
|
||||
"tech company Dubai",
|
||||
"software development company"
|
||||
],
|
||||
openGraph: {
|
||||
title: "About Us | Tech Master - Award-Winning IT Solutions Dubai",
|
||||
description: "Learn about Tech Master, an award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
|
||||
url: "https://tech-masters.guru/about",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/about",
|
||||
},
|
||||
};
|
||||
|
||||
export default function AboutLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
598
src/app/about/page.module.css
Normal file
598
src/app/about/page.module.css
Normal file
@@ -0,0 +1,598 @@
|
||||
/* About Page Styles */
|
||||
.main {
|
||||
padding-top: 80px;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.heroSection {
|
||||
position: relative;
|
||||
padding: 128px 0;
|
||||
background: linear-gradient(135deg, #0F0525 0%, #1a0b3a 50%, #2A0B45 100%);
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.backgroundPattern {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.floatingOrb1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 288px;
|
||||
height: 288px;
|
||||
background-color: #8b5cf6;
|
||||
border-radius: 50%;
|
||||
mix-blend-mode: multiply;
|
||||
filter: blur(24px);
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.floatingOrb2 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 288px;
|
||||
height: 288px;
|
||||
background-color: #eab308;
|
||||
border-radius: 50%;
|
||||
mix-blend-mode: multiply;
|
||||
filter: blur(24px);
|
||||
animation: pulse 2s infinite;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.floatingOrb3 {
|
||||
position: absolute;
|
||||
bottom: -32px;
|
||||
left: 80px;
|
||||
width: 288px;
|
||||
height: 288px;
|
||||
background-color: #ec4899;
|
||||
border-radius: 50%;
|
||||
mix-blend-mode: multiply;
|
||||
filter: blur(24px);
|
||||
animation: pulse 2s infinite;
|
||||
animation-delay: 4s;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 32px;
|
||||
line-height: 1.2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.gradientText {
|
||||
background: linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 20px;
|
||||
color: #d1d5db;
|
||||
max-width: 1024px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.heroIcon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 24px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.trustBadge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: 9999px;
|
||||
padding: 12px 24px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.trustBadgeIcon {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.trustBadgeText {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
/* Stats Section */
|
||||
.statsSection {
|
||||
padding: 96px 0;
|
||||
background-color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.statsBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, #faf5ff 0%, #fdf2f8 100%);
|
||||
}
|
||||
|
||||
.statsContainer {
|
||||
position: relative;
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.statsHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.statsTitle {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.statsSubtitle {
|
||||
font-size: 18px;
|
||||
color: #6b7280;
|
||||
max-width: 512px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.statCard {
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.statCard:hover {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
.statIcon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 24px;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.statCard:hover .statIcon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.statIconYellow {
|
||||
background: linear-gradient(135deg, #fbbf24 0%, #f97316 100%);
|
||||
}
|
||||
|
||||
.statIconBlue {
|
||||
background: linear-gradient(135deg, #60a5fa 0%, #8b5cf6 100%);
|
||||
}
|
||||
|
||||
.statIconGreen {
|
||||
background: linear-gradient(135deg, #4ade80 0%, #14b8a6 100%);
|
||||
}
|
||||
|
||||
.statIconPink {
|
||||
background: linear-gradient(135deg, #f472b6 0%, #ef4444 100%);
|
||||
}
|
||||
|
||||
.statNumber {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1f2937;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.statCard:hover .statNumber {
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.statLabel {
|
||||
color: #6b7280;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Story Section */
|
||||
.storySection {
|
||||
padding: 96px 0;
|
||||
background: linear-gradient(135deg, #f9fafb 0%, #ffffff 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.storyBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(139, 92, 246, 0.1) 0%, rgba(236, 72, 153, 0.1) 100%);
|
||||
}
|
||||
|
||||
.storyContainer {
|
||||
position: relative;
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.journeyBadge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 9999px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.storyTitle {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 32px;
|
||||
line-height: 1.2;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.storyText {
|
||||
font-size: 18px;
|
||||
color: #374151;
|
||||
margin-bottom: 32px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.timelineGrid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.timelineCard {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #f3f4f6;
|
||||
}
|
||||
|
||||
.timelineYear {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 4px;
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.timelineLabel {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.storyVisual {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mainCircle {
|
||||
width: 320px;
|
||||
height: 320px;
|
||||
margin: 0 auto;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 50%, #f97316 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.mainIcon {
|
||||
font-size: 96px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.floatingBadge1 {
|
||||
position: absolute;
|
||||
top: -16px;
|
||||
right: -16px;
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
background: linear-gradient(135deg, #eab308 0%, #f97316 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.floatingBadge2 {
|
||||
position: absolute;
|
||||
bottom: -16px;
|
||||
left: -16px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: linear-gradient(135deg, #4ade80 0%, #14b8a6 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.badgeIcon {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Values Section */
|
||||
.valuesSection {
|
||||
padding: 96px 0;
|
||||
background-color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.valuesBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, #f9fafb 0%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.valuesContainer {
|
||||
position: relative;
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.valuesHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.valuesTitle {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.valuesSubtitle {
|
||||
font-size: 18px;
|
||||
color: #6b7280;
|
||||
max-width: 512px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.valueCard {
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.valueCard:hover {
|
||||
background-color: white;
|
||||
box-shadow: 0 20px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.valueCardBody {
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
.valueIcon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0 auto 24px;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.valueCard:hover .valueIcon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.valueIconBlue {
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||
}
|
||||
|
||||
.valueIconYellow {
|
||||
background: linear-gradient(135deg, #eab308 0%, #f97316 100%);
|
||||
}
|
||||
|
||||
.valueIconGreen {
|
||||
background: linear-gradient(135deg, #22c55e 0%, #14b8a6 100%);
|
||||
}
|
||||
|
||||
.valueIconIndigo {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #3b82f6 100%);
|
||||
}
|
||||
|
||||
.valueTitle {
|
||||
margin-bottom: 16px;
|
||||
color: #1f2937;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.valueCard:hover .valueTitle {
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.valueDescription {
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Team Section */
|
||||
.teamSection {
|
||||
padding: 96px 0;
|
||||
background: linear-gradient(135deg, #f9fafb 0%, #ffffff 100%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.teamBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(139, 92, 246, 0.1) 0%, rgba(236, 72, 153, 0.1) 100%);
|
||||
}
|
||||
|
||||
.teamContainer {
|
||||
position: relative;
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.teamHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.teamTitle {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.teamSubtitle {
|
||||
font-size: 18px;
|
||||
color: #6b7280;
|
||||
max-width: 512px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.teamCard {
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.teamCard:hover {
|
||||
background-color: white;
|
||||
box-shadow: 0 20px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.avatarContainer {
|
||||
position: relative;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.teamAvatar {
|
||||
margin: 0 auto;
|
||||
border: 4px solid white;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.teamCard:hover .teamAvatar {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.verificationBadge {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
right: -8px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.verificationIcon {
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.teamMemberName {
|
||||
margin-bottom: 8px;
|
||||
color: #1f2937;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.teamCard:hover .teamMemberName {
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.teamMemberRole {
|
||||
color: #6b7280;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.teamMemberDescription {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.mainCircle {
|
||||
width: 240px;
|
||||
height: 240px;
|
||||
}
|
||||
|
||||
.mainIcon {
|
||||
font-size: 72px;
|
||||
}
|
||||
|
||||
.timelineGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.floatingOrb1,
|
||||
.floatingOrb2,
|
||||
.floatingOrb3 {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
399
src/app/about/page.tsx
Normal file
399
src/app/about/page.tsx
Normal file
@@ -0,0 +1,399 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
BulbOutlined,
|
||||
CheckCircleOutlined,
|
||||
GlobalOutlined,
|
||||
HeartOutlined,
|
||||
RocketOutlined,
|
||||
StarOutlined,
|
||||
TeamOutlined,
|
||||
TrophyOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Avatar, Card, Col, Row } from "antd";
|
||||
import Paragraph from "antd/es/typography/Paragraph";
|
||||
import Title from "antd/es/typography/Title";
|
||||
import { motion } from "framer-motion";
|
||||
import Footer from "../components/Footer/Footer";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
export default function AboutPage() {
|
||||
const stats = [
|
||||
{
|
||||
icon: <TrophyOutlined />,
|
||||
number: "50+",
|
||||
label: "Projects Completed",
|
||||
color: "from-yellow-400 to-orange-500",
|
||||
},
|
||||
{
|
||||
icon: <GlobalOutlined />,
|
||||
number: "25+",
|
||||
label: "Happy Clients",
|
||||
color: "from-blue-400 to-purple-500",
|
||||
},
|
||||
{
|
||||
icon: <TeamOutlined />,
|
||||
number: "15+",
|
||||
label: "Expert Developers",
|
||||
color: "from-green-400 to-teal-500",
|
||||
},
|
||||
{
|
||||
icon: <RocketOutlined />,
|
||||
number: "3+",
|
||||
label: "Years Experience",
|
||||
color: "from-pink-400 to-red-500",
|
||||
},
|
||||
];
|
||||
|
||||
const values = [
|
||||
{
|
||||
title: "Innovation First",
|
||||
description:
|
||||
"We stay ahead of technology trends to deliver cutting-edge solutions that give our clients a competitive advantage.",
|
||||
icon: <RocketOutlined />,
|
||||
color: "from-blue-500 to-purple-600",
|
||||
},
|
||||
{
|
||||
title: "Quality Excellence",
|
||||
description:
|
||||
"Every project is crafted with attention to detail, ensuring the highest standards of quality and performance.",
|
||||
icon: <StarOutlined />,
|
||||
color: "from-yellow-500 to-orange-600",
|
||||
},
|
||||
{
|
||||
title: "Client Success",
|
||||
description:
|
||||
"Your success is our success. We work closely with clients to understand their needs and deliver solutions that exceed expectations.",
|
||||
icon: <CheckCircleOutlined />,
|
||||
color: "from-green-500 to-teal-600",
|
||||
},
|
||||
{
|
||||
title: "Transparency",
|
||||
description:
|
||||
"We believe in open communication and transparent processes, keeping you informed at every step of your project.",
|
||||
icon: <GlobalOutlined />,
|
||||
color: "from-indigo-500 to-blue-600",
|
||||
},
|
||||
];
|
||||
|
||||
const teamMembers = [
|
||||
{
|
||||
name: "Ahmed Hassan",
|
||||
role: "CEO & Founder",
|
||||
description: "Visionary leader with 10+ years in digital transformation",
|
||||
avatar: "https://randomuser.me/api/portraits/men/32.jpg",
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
name: "Sarah Johnson",
|
||||
role: "CTO",
|
||||
description: "Technical expert specializing in AI and cloud solutions",
|
||||
avatar: "https://randomuser.me/api/portraits/women/44.jpg",
|
||||
delay: 0.1,
|
||||
},
|
||||
{
|
||||
name: "Raj Patel",
|
||||
role: "Lead Developer",
|
||||
description: "Full-stack developer with expertise in modern frameworks",
|
||||
avatar: "https://randomuser.me/api/portraits/men/67.jpg",
|
||||
delay: 0.2,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
{/* Hero Section */}
|
||||
<section className={styles.heroSection}>
|
||||
{/* Background Pattern */}
|
||||
<div className={styles.backgroundPattern}>
|
||||
<div className={styles.floatingOrb1}></div>
|
||||
<div className={styles.floatingOrb2}></div>
|
||||
<div className={styles.floatingOrb3}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.heroContent}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="text-center"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ scale: 0.8 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
className="inline-block mb-6"
|
||||
>
|
||||
<div className={styles.heroIcon}>
|
||||
<BulbOutlined style={{ fontSize: "32px", color: "white" }} />
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<Title level={1} className={styles.heroTitle}>
|
||||
About <span className={styles.gradientText}>Tech Master</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.heroSubtitle}>
|
||||
From Dubai to the stars, we're an award-winning technology
|
||||
agency dedicated to transforming businesses through innovative
|
||||
digital solutions that drive growth and success.
|
||||
</Paragraph>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className="mt-8"
|
||||
>
|
||||
<div className={styles.trustBadge}>
|
||||
<HeartOutlined className={styles.trustBadgeIcon} />
|
||||
<span className={styles.trustBadgeText}>
|
||||
Trusted by 25+ companies worldwide
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Stats Section */}
|
||||
<section className={styles.statsSection}>
|
||||
<div className={styles.statsBackground}></div>
|
||||
<div className={styles.statsContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className={styles.statsHeader}
|
||||
>
|
||||
<Title level={2} className={styles.statsTitle}>
|
||||
Our <span className={styles.gradientText}>Achievements</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.statsSubtitle}>
|
||||
Numbers that speak for our commitment to excellence and innovation
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<Row gutter={[32, 32]} justify="center">
|
||||
{stats.map((stat, index) => (
|
||||
<Col xs={24} sm={12} md={6} key={index}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: index * 0.1 }}
|
||||
className={styles.statCard}
|
||||
>
|
||||
<div
|
||||
className={`${styles.statIcon} ${
|
||||
stat.color.includes("yellow")
|
||||
? styles.statIconYellow
|
||||
: stat.color.includes("blue")
|
||||
? styles.statIconBlue
|
||||
: stat.color.includes("green")
|
||||
? styles.statIconGreen
|
||||
: styles.statIconPink
|
||||
}`}
|
||||
>
|
||||
<div style={{ fontSize: "24px", color: "white" }}>
|
||||
{stat.icon}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.statNumber}>{stat.number}</div>
|
||||
<div className={styles.statLabel}>{stat.label}</div>
|
||||
</motion.div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Story Section */}
|
||||
<section className={styles.storySection}>
|
||||
<div className={styles.storyBackground}></div>
|
||||
<div className={styles.storyContainer}>
|
||||
<Row gutter={[64, 64]} align="middle">
|
||||
<Col xs={24} lg={12}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<div className={styles.journeyBadge}>
|
||||
<RocketOutlined />
|
||||
<span>Our Journey</span>
|
||||
</div>
|
||||
<Title level={2} className={styles.storyTitle}>
|
||||
Our <span className={styles.gradientText}>Story</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.storyText}>
|
||||
Founded in 2020, Tech Master emerged from a vision to bridge
|
||||
the gap between traditional business practices and
|
||||
cutting-edge technology. Based in Dubai, we've grown from
|
||||
a small startup to an award-winning technology agency serving
|
||||
clients across the UAE and beyond.
|
||||
</Paragraph>
|
||||
<Paragraph className={styles.storyText}>
|
||||
Our journey has been marked by continuous innovation,
|
||||
unwavering commitment to quality, and a deep understanding of
|
||||
our clients' needs. We believe that technology should be
|
||||
an enabler, not a barrier, and we work tirelessly to make
|
||||
digital transformation accessible to businesses of all sizes.
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.timelineGrid}>
|
||||
<div className={styles.timelineCard}>
|
||||
<div className={styles.timelineYear}>2020</div>
|
||||
<div className={styles.timelineLabel}>Founded</div>
|
||||
</div>
|
||||
<div className={styles.timelineCard}>
|
||||
<div className={styles.timelineYear}>2024</div>
|
||||
<div className={styles.timelineLabel}>Award Winner</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Col>
|
||||
<Col xs={24} lg={12}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className={styles.storyVisual}
|
||||
>
|
||||
<div className="relative">
|
||||
<div className={styles.mainCircle}>
|
||||
<GlobalOutlined className={styles.mainIcon} />
|
||||
</div>
|
||||
<div className={styles.floatingBadge1}>
|
||||
<TrophyOutlined className={styles.badgeIcon} />
|
||||
</div>
|
||||
<div className={styles.floatingBadge2}>
|
||||
<StarOutlined className={styles.badgeIcon} />
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Values Section */}
|
||||
<section className={styles.valuesSection}>
|
||||
<div className={styles.valuesBackground}></div>
|
||||
<div className={styles.valuesContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className={styles.valuesHeader}
|
||||
>
|
||||
<Title level={2} className={styles.valuesTitle}>
|
||||
Our <span className={styles.gradientText}>Values</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.valuesSubtitle}>
|
||||
These core values guide everything we do and shape the way we
|
||||
approach every project and client relationship.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<Row gutter={[32, 32]}>
|
||||
{values.map((value, index) => (
|
||||
<Col xs={24} sm={12} lg={6} key={index}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: index * 0.1 }}
|
||||
className="h-full"
|
||||
>
|
||||
<Card
|
||||
className={styles.valueCard}
|
||||
bodyStyle={{ padding: "2rem" }}
|
||||
>
|
||||
<div
|
||||
className={`${styles.valueIcon} ${
|
||||
value.color.includes("blue")
|
||||
? styles.valueIconBlue
|
||||
: value.color.includes("yellow")
|
||||
? styles.valueIconYellow
|
||||
: value.color.includes("green")
|
||||
? styles.valueIconGreen
|
||||
: styles.valueIconIndigo
|
||||
}`}
|
||||
>
|
||||
<div style={{ fontSize: "24px", color: "white" }}>
|
||||
{value.icon}
|
||||
</div>
|
||||
</div>
|
||||
<Title level={4} className={styles.valueTitle}>
|
||||
{value.title}
|
||||
</Title>
|
||||
<Paragraph className={styles.valueDescription}>
|
||||
{value.description}
|
||||
</Paragraph>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Team Section */}
|
||||
<section className={styles.teamSection}>
|
||||
<div className={styles.teamBackground}></div>
|
||||
<div className={styles.teamContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className={styles.teamHeader}
|
||||
>
|
||||
<Title level={2} className={styles.teamTitle}>
|
||||
Meet Our <span className={styles.gradientText}>Team</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.teamSubtitle}>
|
||||
Meet the passionate professionals behind Tech Master's
|
||||
success. Our diverse team brings together expertise from various
|
||||
domains to deliver exceptional results.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<Row gutter={[32, 32]} justify="center">
|
||||
{teamMembers.map((member, index) => (
|
||||
<Col xs={24} sm={12} md={8} key={index}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: member.delay }}
|
||||
className="text-center group"
|
||||
>
|
||||
<Card className={styles.teamCard}>
|
||||
<div className={styles.avatarContainer}>
|
||||
<Avatar
|
||||
size={140}
|
||||
src={member.avatar}
|
||||
className={styles.teamAvatar}
|
||||
/>
|
||||
<div className={styles.verificationBadge}>
|
||||
<StarOutlined className={styles.verificationIcon} />
|
||||
</div>
|
||||
</div>
|
||||
<Title level={4} className={styles.teamMemberName}>
|
||||
{member.name}
|
||||
</Title>
|
||||
<Paragraph className={styles.teamMemberRole}>
|
||||
{member.role}
|
||||
</Paragraph>
|
||||
<Paragraph className={styles.teamMemberDescription}>
|
||||
{member.description}
|
||||
</Paragraph>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
// File: src/components/home/ContactSection.tsx
|
||||
|
||||
import {
|
||||
EnvironmentOutlined,
|
||||
MailOutlined,
|
||||
PhoneOutlined,
|
||||
SendOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Button, Col, Form, Input, message, Row, Typography } from "antd";
|
||||
import { motion } from "framer-motion";
|
||||
import Image from "next/image";
|
||||
import React, { useState } from "react";
|
||||
import styles from "./ContactSection.module.css";
|
||||
|
||||
const { Title, Paragraph, Text } = Typography;
|
||||
const { TextArea } = Input;
|
||||
|
||||
const ContactSection: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setSubmitting(true);
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
message.success("Your message has been sent successfully!");
|
||||
form.resetFields();
|
||||
setSubmitting(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.5 },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={styles.contactSection}>
|
||||
<div className={styles.backgroundElements}>
|
||||
<div className={styles.glowOrbTop}></div>
|
||||
<div className={styles.glowOrbBottom}></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}>
|
||||
Get In Touch
|
||||
</Title>
|
||||
<Paragraph className={styles.sectionSubtitle}>
|
||||
Ready to transform your ideas into reality? Contact us today.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<Row gutter={[48, 48]} className={styles.contactContent}>
|
||||
<Col xs={24} lg={10}>
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.contactInfo}
|
||||
>
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div className={styles.iconWrapper}>
|
||||
<MailOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Email
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>
|
||||
info@techmaster.com
|
||||
</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div className={styles.iconWrapper}>
|
||||
<PhoneOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Phone
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>+1 (555) 123-4567</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div className={styles.iconWrapper}>
|
||||
<EnvironmentOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Address
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>
|
||||
1234 Tech Boulevard, Innovation District
|
||||
<br />
|
||||
San Francisco, CA 94105
|
||||
</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.mapContainer}
|
||||
>
|
||||
<Image
|
||||
src="/api/placeholder/400/200"
|
||||
alt="Office Location Map"
|
||||
className={styles.mapImage}
|
||||
width={400}
|
||||
height={400}
|
||||
/>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={14}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.contactForm}
|
||||
>
|
||||
<Title level={4} className={styles.formTitle}>
|
||||
Send Us a Message
|
||||
</Title>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={handleSubmit}
|
||||
className={styles.form}
|
||||
>
|
||||
<Row gutter={16}>
|
||||
<Col xs={24} sm={12}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="Name"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your name" },
|
||||
]}
|
||||
>
|
||||
<Input size="large" placeholder="Your name" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xs={24} sm={12}>
|
||||
<Form.Item
|
||||
name="email"
|
||||
label="Email"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your email" },
|
||||
{
|
||||
type: "email",
|
||||
message: "Please enter a valid email",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input size="large" placeholder="Your email" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Form.Item
|
||||
name="subject"
|
||||
label="Subject"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter a subject" },
|
||||
]}
|
||||
>
|
||||
<Input size="large" placeholder="How can we help you?" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="message"
|
||||
label="Message"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your message" },
|
||||
]}
|
||||
>
|
||||
<TextArea
|
||||
rows={5}
|
||||
placeholder="Tell us about your project..."
|
||||
className={styles.messageInput}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
size="large"
|
||||
icon={<SendOutlined />}
|
||||
loading={submitting}
|
||||
className={styles.submitButton}
|
||||
>
|
||||
Send Message
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</motion.div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContactSection;
|
||||
@@ -1,190 +0,0 @@
|
||||
/* File: src/components/home/ContactSection.module.css */
|
||||
|
||||
.contactSection {
|
||||
padding: 100px 0;
|
||||
background-color: #f8f9fa;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.backgroundElements {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.glowOrbTop {
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-glow);
|
||||
top: -200px;
|
||||
left: -150px;
|
||||
filter: blur(50px);
|
||||
}
|
||||
|
||||
.glowOrbBottom {
|
||||
position: absolute;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(64, 169, 255, 0.15) 0%,
|
||||
rgba(64, 169, 255, 0.05) 50%,
|
||||
rgba(0, 0, 0, 0) 70%
|
||||
);
|
||||
bottom: -250px;
|
||||
right: -200px;
|
||||
filter: blur(60px);
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.contactContent {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05);
|
||||
backdrop-filter: blur(8px);
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.contactInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.contactInfoItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 8px rgba(152, 71, 232, 0.2);
|
||||
}
|
||||
|
||||
.contactIcon {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.contactLabel {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.contactValue {
|
||||
color: #666;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.mapContainer {
|
||||
margin-top: 16px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.mapImage {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.contactForm {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.formTitle {
|
||||
margin-bottom: 24px !important;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.messageInput {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
height: 48px;
|
||||
padding: 0 32px;
|
||||
border-radius: 24px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.submitButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.contactContent {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.contactForm {
|
||||
padding: 24px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contactSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.mapContainer {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
494
src/app/components/Footer/Footer.module.css
Normal file
494
src/app/components/Footer/Footer.module.css
Normal file
@@ -0,0 +1,494 @@
|
||||
/* Footer Component Styles */
|
||||
.footer {
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #0F0525 0%, #1a0b3a 50%, #2A0B45 100%);
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
padding: 80px 0 40px;
|
||||
}
|
||||
|
||||
.footerBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.footerOrb1 {
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(40px);
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.footerOrb2 {
|
||||
position: absolute;
|
||||
bottom: -150px;
|
||||
right: -100px;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(35px);
|
||||
animation: float 10s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.footerContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.footerContent {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 40px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.footerColumn {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footerColumnTitle {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.footerColumnTitle:hover {
|
||||
color: #a855f7;
|
||||
}
|
||||
|
||||
.footerColumnIcon {
|
||||
color: #a855f7;
|
||||
font-size: 1.2rem;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.footerColumnTitle:hover .footerColumnIcon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.footerLinks {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.footerLink {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.footerLink a {
|
||||
color: #cbd5e1;
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
min-height: 44px; /* Better touch target */
|
||||
border-radius: 6px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.footerLink a:hover {
|
||||
color: #a855f7;
|
||||
transform: translateX(6px);
|
||||
background: rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
.footerLinkIcon {
|
||||
font-size: 0.8rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.footerBottom {
|
||||
text-align: center;
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.footerBottomText {
|
||||
color: #94a3b8;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 30px;
|
||||
max-width: 600px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(8px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
min-width: 45px; /* Ensure minimum touch target */
|
||||
min-height: 45px;
|
||||
}
|
||||
|
||||
.socialLink:hover {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
transform: translateY(-3px);
|
||||
color: white;
|
||||
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
||||
}
|
||||
|
||||
.socialLink:active {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(139, 92, 246, 0.4);
|
||||
}
|
||||
|
||||
.copyright {
|
||||
color: #64748b;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copyright a {
|
||||
color: #94a3b8;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
min-height: 32px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copyright a:hover {
|
||||
color: #a855f7;
|
||||
background: rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
/* Mobile-specific enhancements */
|
||||
.mobileFooterColumn {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mobileFooterColumn:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mobileFooterTitle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: 12px 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mobileFooterTitle::after {
|
||||
content: '+';
|
||||
font-size: 1.2rem;
|
||||
color: #a855f7;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.mobileFooterTitle.expanded::after {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.mobileFooterLinks {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.mobileFooterLinks.expanded {
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1024px) {
|
||||
.footerContent {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.footer {
|
||||
padding: 60px 0 30px;
|
||||
}
|
||||
|
||||
.footerContainer {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.footerContent {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.footerColumn {
|
||||
text-align: left;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.footerColumnTitle {
|
||||
justify-content: space-between;
|
||||
font-size: 1.05rem;
|
||||
padding: 16px 0;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.footerColumnTitle::after {
|
||||
content: '+';
|
||||
font-size: 1.3rem;
|
||||
color: #a855f7;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.footerColumnTitle.expanded::after {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.footerLinks {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.footerLinks.expanded {
|
||||
max-height: 300px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.footerLink {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.footerLink a {
|
||||
justify-content: flex-start;
|
||||
font-size: 0.95rem;
|
||||
padding: 12px 0;
|
||||
min-height: 48px;
|
||||
border-radius: 8px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.footerLink a:hover {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
gap: 16px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
min-width: 48px;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.footerBottomText {
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 25px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 0.8rem;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.copyright a {
|
||||
padding: 8px 12px;
|
||||
min-height: 36px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.footer {
|
||||
padding: 50px 0 25px;
|
||||
}
|
||||
|
||||
.footerContainer {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.footerContent {
|
||||
gap: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.footerColumnTitle {
|
||||
font-size: 1rem;
|
||||
padding: 14px 0;
|
||||
}
|
||||
|
||||
.footerColumnTitle::after {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.footerLinks.expanded {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.footerLink a {
|
||||
font-size: 0.9rem;
|
||||
padding: 10px 0;
|
||||
min-height: 44px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.footerBottomText {
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 0.75rem;
|
||||
gap: 10px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.copyright a {
|
||||
padding: 6px 10px;
|
||||
min-height: 32px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.footer {
|
||||
padding: 40px 0 20px;
|
||||
}
|
||||
|
||||
.footerContainer {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.footerColumnTitle {
|
||||
font-size: 0.95rem;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.footerLink a {
|
||||
font-size: 0.85rem;
|
||||
padding: 8px 0;
|
||||
min-height: 40px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
min-width: 40px;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.footerBottomText {
|
||||
font-size: 0.85rem;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 0.7rem;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch device optimizations */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.footerLink a:hover {
|
||||
transform: none;
|
||||
background: rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
.socialLink:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.socialLink:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.footerColumnTitle:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.footerColumnTitle:hover .footerColumnIcon {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
240
src/app/components/Footer/Footer.tsx
Normal file
240
src/app/components/Footer/Footer.tsx
Normal file
@@ -0,0 +1,240 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ArrowRightOutlined,
|
||||
BulbOutlined,
|
||||
EnvironmentOutlined,
|
||||
FacebookOutlined,
|
||||
InstagramOutlined,
|
||||
LinkedinOutlined,
|
||||
MailOutlined,
|
||||
PhoneOutlined,
|
||||
TeamOutlined,
|
||||
TrophyOutlined,
|
||||
TwitterOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { Typography } from 'antd';
|
||||
import { motion } from 'framer-motion';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const [expandedSections, setExpandedSections] = useState<{ [key: string]: boolean }>({});
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth <= 768);
|
||||
};
|
||||
|
||||
checkMobile();
|
||||
window.addEventListener('resize', checkMobile);
|
||||
|
||||
return () => window.removeEventListener('resize', checkMobile);
|
||||
}, []);
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.5 }
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSection = (sectionKey: string) => {
|
||||
if (isMobile) {
|
||||
setExpandedSections(prev => ({
|
||||
...prev,
|
||||
[sectionKey]: !prev[sectionKey]
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const footerSections = [
|
||||
{
|
||||
key: 'company',
|
||||
title: 'Company',
|
||||
icon: <TeamOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/about', text: 'About Us' },
|
||||
{ href: '/services', text: 'Our Services' },
|
||||
{ href: '/projects', text: 'Portfolio' },
|
||||
{ href: '/contact', text: 'Contact Us' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'services',
|
||||
title: 'Services',
|
||||
icon: <BulbOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/services#webdev', text: 'Web Development' },
|
||||
{ href: '/services#mobile', text: 'Mobile Apps' },
|
||||
{ href: '/services#ai', text: 'AI Solutions' },
|
||||
{ href: '/services#cloud', text: 'Cloud Services' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'resources',
|
||||
title: 'Resources',
|
||||
icon: <TrophyOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: '/blog', text: 'Blog & Insights' },
|
||||
{ href: '/case-studies', text: 'Case Studies' },
|
||||
{ href: '/whitepapers', text: 'Whitepapers' },
|
||||
{ href: '/webinars', text: 'Webinars' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'contact',
|
||||
title: 'Contact Info',
|
||||
icon: <MailOutlined className={styles.footerColumnIcon} />,
|
||||
links: [
|
||||
{ href: 'mailto:info@techmaster.com', text: 'info@techmaster.com' },
|
||||
{ href: 'tel:+15551234567', text: '+1 (555) 123-4567' },
|
||||
{ href: '#', text: 'San Francisco, CA' },
|
||||
{ href: '/support', text: '24/7 Support' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const getLinkIcon = (href: string) => {
|
||||
if (href.startsWith('mailto:')) return <MailOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.startsWith('tel:')) return <PhoneOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.includes('support')) return <ArrowRightOutlined className={styles.footerLinkIcon} />;
|
||||
if (href.includes('San Francisco')) return <EnvironmentOutlined className={styles.footerLinkIcon} />;
|
||||
return <ArrowRightOutlined className={styles.footerLinkIcon} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.footerBackground}>
|
||||
<div className={styles.footerOrb1}></div>
|
||||
<div className={styles.footerOrb2}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.footerContainer}>
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.footerContent}
|
||||
>
|
||||
{footerSections.map((section) => (
|
||||
<motion.div
|
||||
key={section.key}
|
||||
variants={itemVariants}
|
||||
className={`${styles.footerColumn} ${isMobile ? styles.mobileFooterColumn : ''}`}
|
||||
>
|
||||
<div
|
||||
className={`${styles.footerColumnTitle} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}
|
||||
onClick={() => toggleSection(section.key)}
|
||||
role={isMobile ? 'button' : undefined}
|
||||
tabIndex={isMobile ? 0 : undefined}
|
||||
onKeyDown={(e) => {
|
||||
if (isMobile && (e.key === 'Enter' || e.key === ' ')) {
|
||||
e.preventDefault();
|
||||
toggleSection(section.key);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
{section.icon}
|
||||
{section.title}
|
||||
</div>
|
||||
</div>
|
||||
<ul className={`${styles.footerLinks} ${isMobile && expandedSections[section.key] ? styles.expanded : ''}`}>
|
||||
{section.links.map((link, index) => (
|
||||
<li key={index} className={styles.footerLink}>
|
||||
<a
|
||||
href={link.href}
|
||||
onClick={(e) => {
|
||||
// Prevent navigation if it's a placeholder link
|
||||
if (link.href === '#') {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getLinkIcon(link.href)}
|
||||
{link.text}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.3 }}
|
||||
viewport={{ once: true }}
|
||||
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}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Facebook"
|
||||
>
|
||||
<FacebookOutlined />
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Twitter"
|
||||
>
|
||||
<TwitterOutlined />
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<LinkedinOutlined />
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className={styles.socialLink}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
aria-label="Instagram"
|
||||
>
|
||||
<InstagramOutlined />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className={styles.copyright}>
|
||||
<span>© 2024 Tech Master. All rights reserved.</span>
|
||||
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap', justifyContent: 'center' }}>
|
||||
<a href="/privacy" onClick={(e) => e.preventDefault()}>Privacy Policy</a>
|
||||
<a href="/terms" onClick={(e) => e.preventDefault()}>Terms of Service</a>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
@@ -5,37 +5,97 @@
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
|
||||
padding: 15px 0;
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid rgba(116, 0, 184, 0.1);
|
||||
padding: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.headerContainer {
|
||||
max-width: 1200px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
padding: 0 32px;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
/* Logo Section */
|
||||
.logoSection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logoLink {
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logoContainer {
|
||||
/* background: var(--primary) !important; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logoIcon {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 8px;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.logoDot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.logoDot:nth-child(2) {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.logoDot:nth-child(3) {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.logoText {
|
||||
color: #6e48aa !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #5e60ce 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
margin: 0 !important;
|
||||
font-weight: 700 !important;
|
||||
font-size: 1.5rem !important;
|
||||
font-weight: 800 !important;
|
||||
font-size: 1.6rem !important;
|
||||
letter-spacing: -0.5px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.logoHighlight {
|
||||
margin-left: 8px;
|
||||
.logoText:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
/* Navigation Section */
|
||||
.navSection {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navContainer {
|
||||
@@ -46,31 +106,229 @@
|
||||
.menu {
|
||||
border-bottom: none !important;
|
||||
background: transparent !important;
|
||||
font-weight: 500;
|
||||
font-weight: 500 !important;
|
||||
font-size: 0.95rem !important;
|
||||
}
|
||||
|
||||
.menu li {
|
||||
padding: 0 15px !important;
|
||||
.menu :global(.ant-menu-item) {
|
||||
padding: 12px 20px !important;
|
||||
margin: 0 4px !important;
|
||||
border-radius: 12px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
color: #666 !important;
|
||||
font-weight: 500 !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
margin-left: 30px;
|
||||
.menu :global(.ant-menu-item::before) {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* .menu :global(.ant-menu-item:hover) {
|
||||
color: #7400b8 !important;
|
||||
transform: translateY(-2px) !important;
|
||||
box-shadow: 0 8px 25px rgba(116, 0, 184, 0.15) !important;
|
||||
} */
|
||||
|
||||
.menu :global(.ant-menu-item:hover::before) {
|
||||
/* opacity: 0.1; */
|
||||
}
|
||||
|
||||
.menu :global(.ant-menu-item-selected) {
|
||||
color: #7400b8 !important;
|
||||
/* background: rgba(116, 0, 184, 0.1) !important; */
|
||||
font-weight: 600 !important;
|
||||
/* box-shadow: 0 4px 15px rgba(116, 0, 184, 0.2) !important; */
|
||||
}
|
||||
|
||||
.menu :global(.ant-menu-item::after) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Actions Section */
|
||||
.actionsSection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.actionButtons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 12px !important;
|
||||
border: 1px solid rgba(116, 0, 184, 0.1) !important;
|
||||
background: rgba(255, 255, 255, 0.8) !important;
|
||||
color: #666 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease !important;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
|
||||
.actionButton:hover {
|
||||
background: rgba(116, 0, 184, 0.1) !important;
|
||||
color: #7400b8 !important;
|
||||
transform: translateY(-2px) !important;
|
||||
box-shadow: 0 8px 20px rgba(116, 0, 184, 0.2) !important;
|
||||
border-color: rgba(116, 0, 184, 0.2) !important;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
/* background: var(--primary) !important; */
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%) !important;
|
||||
border: none !important;
|
||||
font-weight: 500 !important;
|
||||
padding: 0 25px !important;
|
||||
font-weight: 600 !important;
|
||||
padding: 0 24px !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 4px 15px rgba(116, 0, 184, 0.3) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
font-size: 0.9rem !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.ctaButton:hover {
|
||||
transform: translateY(-2px) !important;
|
||||
box-shadow: 0 8px 25px rgba(116, 0, 184, 0.4) !important;
|
||||
/* background: linear-gradient(135deg, #6930c3 0%, #5e60ce 100%) !important; */
|
||||
}
|
||||
|
||||
.ctaButton:active {
|
||||
transform: translateY(0) !important;
|
||||
}
|
||||
|
||||
.userAvatar {
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
border-radius: 12px !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%) !important;
|
||||
border: 2px solid rgba(255, 255, 255, 0.8) !important;
|
||||
box-shadow: 0 4px 12px rgba(116, 0, 184, 0.3) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.userAvatar:hover {
|
||||
transform: scale(1.05) !important;
|
||||
box-shadow: 0 8px 20px rgba(116, 0, 184, 0.4) !important;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1200px) {
|
||||
.headerContainer {
|
||||
padding: 0 24px;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.menu :global(.ant-menu-item) {
|
||||
padding: 10px 16px !important;
|
||||
}
|
||||
|
||||
.actionButtons {
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.navContainer {
|
||||
.headerContainer {
|
||||
grid-template-columns: auto auto;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.navSection {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.actionsSection {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-size: 1.4rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.headerContainer {
|
||||
justify-content: center;
|
||||
padding: 0 16px;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-size: 1.3rem !important;
|
||||
}
|
||||
|
||||
.actionButtons {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
padding: 0 20px !important;
|
||||
height: 36px !important;
|
||||
font-size: 0.85rem !important;
|
||||
}
|
||||
|
||||
.userAvatar {
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.headerContainer {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
|
||||
.logoIcon {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.logoDot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
padding: 0 16px !important;
|
||||
height: 32px !important;
|
||||
font-size: 0.8rem !important;
|
||||
}
|
||||
|
||||
.userAvatar {
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Menu, MenuProps, Typography } from "antd";
|
||||
import { BellOutlined, UserOutlined } from "@ant-design/icons";
|
||||
import { Avatar, Button, Menu, MenuProps, Typography } from "antd";
|
||||
import { motion } from "framer-motion";
|
||||
import Link from "next/link";
|
||||
import styles from "./Header.module.css";
|
||||
@@ -34,37 +35,74 @@ const Header = () => {
|
||||
return (
|
||||
<header className={styles.header}>
|
||||
<div className={styles.headerContainer}>
|
||||
{/* Logo Section */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.logoContainer}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className={styles.logoSection}
|
||||
>
|
||||
<Link href="/">
|
||||
<Link href="/" className={styles.logoLink}>
|
||||
<div className={styles.logoContainer}>
|
||||
<div className={styles.logoIcon}>
|
||||
<div className={styles.logoDot}></div>
|
||||
<div className={styles.logoDot}></div>
|
||||
<div className={styles.logoDot}></div>
|
||||
</div>
|
||||
<Title level={3} className={styles.logoText}>
|
||||
Tech Master
|
||||
Tech Masters
|
||||
</Title>
|
||||
</div>
|
||||
</Link>
|
||||
</motion.div>
|
||||
|
||||
<nav className={styles.navContainer}>
|
||||
{/* Navigation Section */}
|
||||
<nav className={styles.navSection}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
className={styles.navContainer}
|
||||
>
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
items={items}
|
||||
className={styles.menu}
|
||||
selectedKeys={['home']}
|
||||
/>
|
||||
</motion.div>
|
||||
</nav>
|
||||
|
||||
{/* <Space className={styles.ctaContainer}>
|
||||
{/* Actions Section */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className={styles.actionsSection}
|
||||
>
|
||||
<div className={styles.actionButtons}>
|
||||
{/* <Button
|
||||
type="text"
|
||||
icon={<SearchOutlined />}
|
||||
className={styles.actionButton}
|
||||
/> */}
|
||||
<Button
|
||||
type="text"
|
||||
icon={<BellOutlined />}
|
||||
className={styles.actionButton}
|
||||
/>
|
||||
{/* <Button
|
||||
type="primary"
|
||||
shape="round"
|
||||
size="large"
|
||||
className={styles.ctaButton}
|
||||
>
|
||||
Get Started
|
||||
</Button>
|
||||
</Space> */}
|
||||
</nav>
|
||||
</Button> */}
|
||||
<Avatar
|
||||
icon={<UserOutlined />}
|
||||
className={styles.userAvatar}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useEffect } from "react";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
particlesJS: any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,6 @@ const preferenceOptions: PreferenceOption[] = [
|
||||
label: "E-commerce Solutions",
|
||||
description: "Online stores, payment gateways, inventory management",
|
||||
},
|
||||
{
|
||||
id: "seo",
|
||||
label: "SEO & Digital Marketing",
|
||||
description: "Search optimization, content strategy, analytics",
|
||||
},
|
||||
// {
|
||||
// id: "mobile",
|
||||
// label: "Mobile Development",
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
// File: src/components/home/ProjectsShowcase.tsx
|
||||
|
||||
import { EyeOutlined, LeftOutlined, RightOutlined } from "@ant-design/icons";
|
||||
import { Badge, Button, Card, Col, Row, Tag, Typography } from "antd";
|
||||
import { motion, useAnimation } from "framer-motion";
|
||||
import Image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Paragraph from "antd/es/typography/Paragraph";
|
||||
import Title from "antd/es/typography/Title";
|
||||
import ProjectsShowcaseClient from "./ProjectsShowcaseClient";
|
||||
import styles from "./ProjectsShowcaseSelector.module.css";
|
||||
|
||||
const { Title, Paragraph, Text } = Typography;
|
||||
|
||||
interface Project {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -17,246 +11,258 @@ interface Project {
|
||||
category: string;
|
||||
technologies: string[];
|
||||
featured: boolean;
|
||||
detailedDescription: string;
|
||||
images: string[];
|
||||
liveUrl?: string;
|
||||
githubUrl?: string;
|
||||
features: string[];
|
||||
duration: string;
|
||||
teamSize: string;
|
||||
}
|
||||
|
||||
// Sample project data
|
||||
const projectsData: Project[] = [
|
||||
{
|
||||
id: "p1",
|
||||
title: "FinTech Dashboard",
|
||||
title: "BPro ERP System",
|
||||
description:
|
||||
"An AI-powered financial analytics platform with real-time data visualization and predictive insights.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "Web Application",
|
||||
technologies: ["React", "Node.js", "TensorFlow", "AWS"],
|
||||
"Comprehensive enterprise resource planning system with advanced business process management and real-time analytics.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
category: "Enterprise Software",
|
||||
technologies: ["React", "Node.js", "PostgreSQL", "Redis"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A comprehensive ERP system designed for modern businesses, featuring advanced business process management, real-time analytics, and seamless integration with existing enterprise systems. The platform streamlines operations across all departments.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
],
|
||||
liveUrl: "https://bpro-erp.com",
|
||||
githubUrl: "https://github.com/company/bpro-erp",
|
||||
features: [
|
||||
"Advanced business process management",
|
||||
"Real-time analytics and reporting",
|
||||
"Multi-department integration",
|
||||
"Custom workflow automation",
|
||||
"Comprehensive audit trails",
|
||||
],
|
||||
duration: "8 months",
|
||||
teamSize: "12 developers",
|
||||
},
|
||||
{
|
||||
id: "p2",
|
||||
title: "Healthcare Management System",
|
||||
title: "Law Office Management",
|
||||
description:
|
||||
"Comprehensive solution for managing patient records, appointments, and medical data with advanced security features.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "Enterprise Software",
|
||||
"Complete legal practice management solution with case tracking, document management, and client portal.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
category: "Legal Software",
|
||||
technologies: ["Angular", ".NET Core", "SQL Server", "Azure"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A comprehensive legal practice management system designed to streamline law office operations, manage cases, track billable hours, and provide secure client communication portals.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
"https://tech-masters.guru/photos/projects/law-office-login.png",
|
||||
"https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
],
|
||||
liveUrl: "https://law-office-demo.com",
|
||||
githubUrl: "https://github.com/company/law-office-system",
|
||||
features: [
|
||||
"Case management and tracking",
|
||||
"Document management system",
|
||||
"Client portal and communication",
|
||||
"Time tracking and billing",
|
||||
"Calendar and appointment management",
|
||||
],
|
||||
duration: "6 months",
|
||||
teamSize: "8 developers",
|
||||
},
|
||||
{
|
||||
id: "p3",
|
||||
title: "E-commerce Marketplace",
|
||||
title: "MoneyOut Payment Platform",
|
||||
description:
|
||||
"Feature-rich online marketplace connecting vendors and customers with integrated payment processing and inventory management.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "E-commerce",
|
||||
"Secure digital payment processing platform with multi-currency support and advanced fraud detection.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
category: "FinTech",
|
||||
technologies: ["Next.js", "Stripe", "MongoDB", "GraphQL"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A modern payment processing platform that enables secure digital transactions with multi-currency support, advanced fraud detection, and comprehensive merchant tools.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
],
|
||||
liveUrl: "https://moneyout-demo.com",
|
||||
githubUrl: "https://github.com/company/moneyout-platform",
|
||||
features: [
|
||||
"Multi-currency payment processing",
|
||||
"Advanced fraud detection",
|
||||
"Merchant dashboard and analytics",
|
||||
"Secure API integration",
|
||||
"Real-time transaction monitoring",
|
||||
],
|
||||
duration: "7 months",
|
||||
teamSize: "10 developers",
|
||||
},
|
||||
{
|
||||
id: "p4",
|
||||
title: "Smart City IoT Platform",
|
||||
title: "Cloths E-commerce Platform",
|
||||
description:
|
||||
"IoT ecosystem for urban monitoring and management, featuring real-time data collection and analytics.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "IoT",
|
||||
technologies: ["Python", "MQTT", "Kubernetes", "TensorFlow"],
|
||||
"Modern fashion e-commerce platform with advanced product catalog, virtual try-on, and personalized recommendations.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
category: "E-commerce",
|
||||
technologies: ["React", "Node.js", "MongoDB", "AWS"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A cutting-edge fashion e-commerce platform featuring virtual try-on technology, personalized recommendations, and seamless mobile shopping experience.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
],
|
||||
liveUrl: "https://cloths-ecommerce.com",
|
||||
githubUrl: "https://github.com/company/cloths-ecommerce",
|
||||
features: [
|
||||
"Virtual try-on technology",
|
||||
"Personalized recommendations",
|
||||
"Advanced product catalog",
|
||||
"Mobile-first design",
|
||||
"Social commerce integration",
|
||||
],
|
||||
duration: "5 months",
|
||||
teamSize: "6 developers",
|
||||
},
|
||||
{
|
||||
id: "p5",
|
||||
title: "Logistics Tracking System",
|
||||
title: "Nanas Dashboard",
|
||||
description:
|
||||
"Real-time fleet management and package tracking solution with route optimization algorithms.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "Mobile & Web",
|
||||
technologies: ["React Native", "Node.js", "PostgreSQL", "Google Maps API"],
|
||||
"Comprehensive business intelligence dashboard with real-time data visualization and predictive analytics.",
|
||||
imageUrl:
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
category: "Business Intelligence",
|
||||
technologies: ["Vue.js", "Python", "PostgreSQL", "Docker"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A powerful business intelligence dashboard that provides real-time data visualization, predictive analytics, and comprehensive reporting for data-driven decision making.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
],
|
||||
liveUrl: "https://nanas-dashboard.com",
|
||||
githubUrl: "https://github.com/company/nanas-dashboard",
|
||||
features: [
|
||||
"Real-time data visualization",
|
||||
"Predictive analytics",
|
||||
"Custom reporting tools",
|
||||
"Interactive dashboards",
|
||||
"Data export capabilities",
|
||||
],
|
||||
duration: "4 months",
|
||||
teamSize: "5 developers",
|
||||
},
|
||||
{
|
||||
id: "p6",
|
||||
title: "Virtual Learning Environment",
|
||||
title: "Easy Pay Login System",
|
||||
description:
|
||||
"Interactive educational platform with personalized learning paths, video conferencing, and progress tracking.",
|
||||
imageUrl: "/api/placeholder/600/400",
|
||||
category: "Education",
|
||||
technologies: ["Vue.js", "Django", "WebRTC", "Docker"],
|
||||
"Secure authentication system with multi-factor authentication and advanced security features for financial applications.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
category: "Security",
|
||||
technologies: ["React", "Node.js", "JWT", "Redis"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A robust authentication system designed for financial applications, featuring multi-factor authentication, advanced security protocols, and seamless user experience.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
],
|
||||
liveUrl: "https://easy-pay-login.com",
|
||||
githubUrl: "https://github.com/company/easy-pay-login",
|
||||
features: [
|
||||
"Multi-factor authentication",
|
||||
"Advanced security protocols",
|
||||
"Session management",
|
||||
"Audit logging",
|
||||
"Password recovery system",
|
||||
],
|
||||
duration: "3 months",
|
||||
teamSize: "4 developers",
|
||||
},
|
||||
{
|
||||
id: "p7",
|
||||
title: "Majsin Dashboard",
|
||||
description:
|
||||
"Advanced analytics dashboard with machine learning insights and customizable reporting for enterprise clients.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
category: "Analytics",
|
||||
technologies: ["Angular", "Python", "TensorFlow", "AWS"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"An advanced analytics dashboard powered by machine learning, providing deep insights and customizable reporting for enterprise-level decision making.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
],
|
||||
liveUrl: "https://majsin-dashboard.com",
|
||||
githubUrl: "https://github.com/company/majsin-dashboard",
|
||||
features: [
|
||||
"Machine learning insights",
|
||||
"Customizable reporting",
|
||||
"Real-time data processing",
|
||||
"Advanced visualizations",
|
||||
"API integration capabilities",
|
||||
],
|
||||
duration: "6 months",
|
||||
teamSize: "7 developers",
|
||||
},
|
||||
{
|
||||
id: "p8",
|
||||
title: "SVU Hardware Management",
|
||||
description:
|
||||
"Comprehensive hardware inventory and management system for educational institutions with asset tracking.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
category: "Education",
|
||||
technologies: ["React", "Node.js", "MySQL", "Docker"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A comprehensive hardware management system designed for educational institutions, featuring asset tracking, maintenance scheduling, and detailed reporting capabilities.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
],
|
||||
liveUrl: "https://svu-hardware.com",
|
||||
githubUrl: "https://github.com/company/svu-hardware",
|
||||
features: [
|
||||
"Asset tracking and management",
|
||||
"Maintenance scheduling",
|
||||
"Inventory control",
|
||||
"Detailed reporting",
|
||||
"User access management",
|
||||
],
|
||||
duration: "5 months",
|
||||
teamSize: "6 developers",
|
||||
},
|
||||
];
|
||||
|
||||
const ProjectsShowcase: React.FC = () => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [visibleProjects, setVisibleProjects] = useState<Project[]>([]);
|
||||
const controls = useAnimation();
|
||||
|
||||
// Determine number of projects to show based on screen width
|
||||
const [projectsPerView, setProjectsPerView] = useState(3);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 768) {
|
||||
setProjectsPerView(1);
|
||||
} else if (window.innerWidth < 992) {
|
||||
setProjectsPerView(2);
|
||||
} else {
|
||||
setProjectsPerView(3);
|
||||
}
|
||||
};
|
||||
|
||||
// Set initial state
|
||||
handleResize();
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Update visible projects whenever currentIndex or projectsPerView changes
|
||||
setVisibleProjects(
|
||||
projectsData.slice(currentIndex, currentIndex + projectsPerView)
|
||||
);
|
||||
}, [currentIndex, projectsPerView]);
|
||||
|
||||
const handleNext = async () => {
|
||||
if (currentIndex + projectsPerView < projectsData.length) {
|
||||
await controls.start({
|
||||
x: "-100%",
|
||||
opacity: 0,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
setCurrentIndex((prev) => prev + 1);
|
||||
controls.start({
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrev = async () => {
|
||||
if (currentIndex > 0) {
|
||||
await controls.start({
|
||||
x: "100%",
|
||||
opacity: 0,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
setCurrentIndex((prev) => prev - 1);
|
||||
controls.start({
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={styles.projectsSection}>
|
||||
<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}
|
||||
>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Title level={2} className={styles.sectionTitle}>
|
||||
Our Work
|
||||
</Title>
|
||||
<Paragraph className={styles.sectionSubtitle}>
|
||||
Transforming ideas into powerful digital solutions
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<div className={styles.showcaseContainer}>
|
||||
<motion.div
|
||||
className={styles.projectsGrid}
|
||||
animate={controls}
|
||||
initial={{ opacity: 1, x: 0 }}
|
||||
>
|
||||
<Row gutter={[24, 24]}>
|
||||
{visibleProjects.map((project) => (
|
||||
<Col xs={24} md={24 / projectsPerView} key={project.id}>
|
||||
<motion.div
|
||||
whileHover={{ y: -10 }}
|
||||
transition={{ type: "spring", stiffness: 300 }}
|
||||
>
|
||||
<Card
|
||||
hoverable
|
||||
cover={
|
||||
<div className={styles.projectImageContainer}>
|
||||
<Image
|
||||
alt={project.title}
|
||||
src={project.imageUrl}
|
||||
className={styles.projectImage}
|
||||
width={400}
|
||||
height={400}
|
||||
/>
|
||||
<div className={styles.projectOverlay}>
|
||||
<Button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon={<EyeOutlined />}
|
||||
className={styles.viewButton}
|
||||
/>
|
||||
</div>
|
||||
{project.featured && (
|
||||
<Badge.Ribbon
|
||||
text="Featured"
|
||||
className={styles.featuredBadge}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
className={styles.projectCard}
|
||||
>
|
||||
<div className={styles.categoryTag}>
|
||||
<Tag color="blue">{project.category}</Tag>
|
||||
</div>
|
||||
<Card.Meta
|
||||
title={project.title}
|
||||
description={project.description}
|
||||
/>
|
||||
<div className={styles.technologiesList}>
|
||||
{project.technologies.map((tech) => (
|
||||
<Tag key={tech} className={styles.techTag}>
|
||||
{tech}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</motion.div>
|
||||
|
||||
<div className={styles.navigationControls}>
|
||||
<Button
|
||||
shape="circle"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={handlePrev}
|
||||
disabled={currentIndex === 0}
|
||||
className={styles.navButton}
|
||||
/>
|
||||
<Text className={styles.pageIndicator}>
|
||||
{currentIndex + 1}-
|
||||
{Math.min(currentIndex + projectsPerView, projectsData.length)} of{" "}
|
||||
{projectsData.length}
|
||||
</Text>
|
||||
<Button
|
||||
shape="circle"
|
||||
icon={<RightOutlined />}
|
||||
onClick={handleNext}
|
||||
disabled={currentIndex + projectsPerView >= projectsData.length}
|
||||
className={styles.navButton}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.viewAllContainer}>
|
||||
<Button type="primary" size="large" className={styles.viewAllButton}>
|
||||
View All Projects
|
||||
</Button>
|
||||
</div>
|
||||
<ProjectsShowcaseClient projects={projectsData} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
364
src/app/components/ProjectsShowcase/ProjectsShowcaseClient.tsx
Normal file
364
src/app/components/ProjectsShowcase/ProjectsShowcaseClient.tsx
Normal file
@@ -0,0 +1,364 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
CloseOutlined,
|
||||
EyeOutlined,
|
||||
LeftOutlined,
|
||||
LinkOutlined,
|
||||
RightOutlined
|
||||
} from "@ant-design/icons";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Card,
|
||||
Carousel,
|
||||
Col,
|
||||
Modal,
|
||||
Row,
|
||||
Tag,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import { AnimatePresence, motion, useAnimation } from "framer-motion";
|
||||
import Image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import styles from "./ProjectsShowcaseSelector.module.css";
|
||||
|
||||
const { Title, Paragraph, Text } = Typography;
|
||||
|
||||
interface Project {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
imageUrl: string;
|
||||
category: string;
|
||||
technologies: string[];
|
||||
featured: boolean;
|
||||
detailedDescription: string;
|
||||
images: string[];
|
||||
liveUrl?: string;
|
||||
githubUrl?: string;
|
||||
features: string[];
|
||||
duration: string;
|
||||
teamSize: string;
|
||||
}
|
||||
|
||||
interface ProjectsShowcaseClientProps {
|
||||
projects: Project[];
|
||||
}
|
||||
|
||||
const ProjectsShowcaseClient: React.FC<ProjectsShowcaseClientProps> = ({
|
||||
projects,
|
||||
}) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [visibleProjects, setVisibleProjects] = useState<Project[]>([]);
|
||||
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const controls = useAnimation();
|
||||
|
||||
// Determine number of projects to show based on screen width
|
||||
const [projectsPerView, setProjectsPerView] = useState(3);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 768) {
|
||||
setProjectsPerView(1);
|
||||
} else if (window.innerWidth < 992) {
|
||||
setProjectsPerView(2);
|
||||
} else {
|
||||
setProjectsPerView(3);
|
||||
}
|
||||
};
|
||||
|
||||
// Set initial state
|
||||
handleResize();
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Update visible projects whenever currentIndex or projectsPerView changes
|
||||
setVisibleProjects(
|
||||
projects.slice(currentIndex, currentIndex + projectsPerView)
|
||||
);
|
||||
}, [currentIndex, projectsPerView, projects]);
|
||||
|
||||
const handleNext = async () => {
|
||||
if (currentIndex + projectsPerView < projects.length) {
|
||||
await controls.start({
|
||||
x: "-100%",
|
||||
opacity: 0,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
setCurrentIndex((prev) => prev + 1);
|
||||
controls.start({
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrev = async () => {
|
||||
if (currentIndex > 0) {
|
||||
await controls.start({
|
||||
x: "100%",
|
||||
opacity: 0,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
setCurrentIndex((prev) => prev - 1);
|
||||
controls.start({
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.3 },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleProjectClick = (project: Project) => {
|
||||
setSelectedProject(project);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleModalClose = () => {
|
||||
setIsModalVisible(false);
|
||||
setTimeout(() => {
|
||||
setSelectedProject(null);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.showcaseContainer}>
|
||||
<motion.div
|
||||
className={styles.projectsGrid}
|
||||
animate={controls}
|
||||
initial={{ opacity: 1, x: 0 }}
|
||||
>
|
||||
<Row gutter={[24, 24]}>
|
||||
{visibleProjects.map((project) => (
|
||||
<Col xs={24} md={24 / projectsPerView} key={project.id}>
|
||||
<motion.div
|
||||
whileHover={{ y: -10 }}
|
||||
transition={{ type: "spring", stiffness: 300 }}
|
||||
>
|
||||
<Card
|
||||
hoverable
|
||||
onClick={() => handleProjectClick(project)}
|
||||
cover={
|
||||
<div className={styles.projectImageContainer}>
|
||||
<Image
|
||||
alt={project.title}
|
||||
src={project.imageUrl}
|
||||
className={styles.projectImage}
|
||||
width={400}
|
||||
height={400}
|
||||
/>
|
||||
<div className={styles.projectOverlay}>
|
||||
<Button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon={<EyeOutlined />}
|
||||
className={styles.viewButton}
|
||||
/>
|
||||
</div>
|
||||
{project.featured && (
|
||||
<Badge.Ribbon
|
||||
text="Featured"
|
||||
className={styles.featuredBadge}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
className={styles.projectCard}
|
||||
>
|
||||
<div className={styles.categoryTag}>
|
||||
<Tag color="blue">{project.category}</Tag>
|
||||
</div>
|
||||
<Card.Meta
|
||||
title={project.title}
|
||||
description={project.description}
|
||||
/>
|
||||
<div className={styles.technologiesList}>
|
||||
{project.technologies.map((tech) => (
|
||||
<Tag key={tech} className={styles.techTag}>
|
||||
{tech}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</motion.div>
|
||||
|
||||
<div className={styles.navigationControls}>
|
||||
<Button
|
||||
shape="circle"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={handlePrev}
|
||||
disabled={currentIndex === 0}
|
||||
className={styles.navButton}
|
||||
/>
|
||||
<Text className={styles.pageIndicator}>
|
||||
{currentIndex + 1}-
|
||||
{Math.min(currentIndex + projectsPerView, projects.length)} of{" "}
|
||||
{projects.length}
|
||||
</Text>
|
||||
<Button
|
||||
shape="circle"
|
||||
icon={<RightOutlined />}
|
||||
onClick={handleNext}
|
||||
disabled={currentIndex + projectsPerView >= projects.length}
|
||||
className={styles.navButton}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.viewAllContainer}>
|
||||
<Button type="primary" size="large" className={styles.viewAllButton}>
|
||||
View All Projects
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Project Details Modal */}
|
||||
<AnimatePresence>
|
||||
{isModalVisible && selectedProject && (
|
||||
<Modal
|
||||
open={isModalVisible}
|
||||
onCancel={handleModalClose}
|
||||
footer={null}
|
||||
width={1000}
|
||||
className={styles.projectModal}
|
||||
closeIcon={<CloseOutlined className={styles.closeIcon} />}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.8 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className={styles.modalContent}
|
||||
>
|
||||
<div className={styles.modalHeader}>
|
||||
<div className={styles.modalTitleSection}>
|
||||
<Title level={2} className={styles.modalTitle}>
|
||||
{selectedProject.title}
|
||||
</Title>
|
||||
<Tag color="blue" className={styles.modalCategory}>
|
||||
{selectedProject.category}
|
||||
</Tag>
|
||||
</div>
|
||||
<div className={styles.modalActions}>
|
||||
{selectedProject.liveUrl && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<LinkOutlined />}
|
||||
href={selectedProject.liveUrl}
|
||||
target="_blank"
|
||||
className={styles.actionButton}
|
||||
>
|
||||
Live Demo
|
||||
</Button>
|
||||
)}
|
||||
{/* {selectedProject.githubUrl && (
|
||||
<Button
|
||||
icon={<GithubOutlined />}
|
||||
href={selectedProject.githubUrl}
|
||||
target="_blank"
|
||||
className={styles.actionButton}
|
||||
>
|
||||
View Code
|
||||
</Button>
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.modalBody}>
|
||||
<div className={styles.projectImages}>
|
||||
<Carousel
|
||||
autoplay
|
||||
dots={{ className: styles.carouselDots }}
|
||||
className={styles.imageCarousel}
|
||||
>
|
||||
{selectedProject.images.map((image, index) => (
|
||||
<div key={index} className={styles.carouselItem}>
|
||||
<Image
|
||||
src={image}
|
||||
alt={`${selectedProject.title} - Image ${index + 1}`}
|
||||
width={800}
|
||||
height={500}
|
||||
className={styles.modalImage}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</Carousel>
|
||||
</div>
|
||||
|
||||
<div className={styles.projectDetails}>
|
||||
<div className={styles.detailSection}>
|
||||
<Title level={4} className={styles.sectionTitle}>
|
||||
Project Overview
|
||||
</Title>
|
||||
<Paragraph className={styles.projectDescription}>
|
||||
{selectedProject.detailedDescription}
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
||||
<div className={styles.detailGrid}>
|
||||
<div className={styles.detailSection}>
|
||||
<Title level={4} className={styles.sectionTitle}>
|
||||
Key Features
|
||||
</Title>
|
||||
<ul className={styles.featuresList}>
|
||||
{selectedProject.features.map((feature, index) => (
|
||||
<motion.li
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
className={styles.featureItem}
|
||||
>
|
||||
{feature}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className={styles.detailSection}>
|
||||
<Title level={4} className={styles.sectionTitle}>
|
||||
Project Details
|
||||
</Title>
|
||||
<div className={styles.projectInfo}>
|
||||
<div className={styles.infoItem}>
|
||||
<Text strong>Duration:</Text>
|
||||
<Text>{selectedProject.duration}</Text>
|
||||
</div>
|
||||
<div className={styles.infoItem}>
|
||||
<Text strong>Team Size:</Text>
|
||||
<Text>{selectedProject.teamSize}</Text>
|
||||
</div>
|
||||
<div className={styles.infoItem}>
|
||||
<Text strong>Technologies:</Text>
|
||||
<div className={styles.modalTechnologies}>
|
||||
{selectedProject.technologies.map((tech) => (
|
||||
<Tag key={tech} className={styles.modalTechTag}>
|
||||
{tech}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Modal>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectsShowcaseClient;
|
||||
@@ -1,43 +1,73 @@
|
||||
/* File: src/components/home/ProjectsShowcase.module.css */
|
||||
|
||||
.projectsSection {
|
||||
padding: 100px 0;
|
||||
background-color: #fff;
|
||||
padding: 120px 0;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.projectsSection::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="hexagons" width="50" height="43.4" patternUnits="userSpaceOnUse"><polygon points="25,2 47,13.4 47,36.6 25,48 3,36.6 3,13.4" fill="none" stroke="%23f1f5f9" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23hexagons)"/></svg>');
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sectionHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 700 !important;
|
||||
margin-bottom: 16px !important;
|
||||
|
||||
font-size: 3rem !important;
|
||||
font-weight: 800 !important;
|
||||
margin-bottom: 20px !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #5e60ce 50%, #4ea8de 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
position: relative;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.sectionTitle::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 80px;
|
||||
height: 5px;
|
||||
background: linear-gradient(90deg, #7400b8, #6930c3);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 8px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.sectionSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #666;
|
||||
max-width: 600px;
|
||||
font-size: 1.2rem;
|
||||
color: #64748b;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.7;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.showcaseContainer {
|
||||
position: relative;
|
||||
padding: 20px 0;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.projectsGrid {
|
||||
@@ -46,12 +76,37 @@
|
||||
}
|
||||
|
||||
.projectCard {
|
||||
height: 100%;
|
||||
border-radius: 12px;
|
||||
height: fit-content;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.projectCard::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(116, 0, 184, 0.05) 0%, rgba(94, 96, 206, 0.05) 100%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.projectCard:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.projectCard:hover {
|
||||
transform: translateY(-12px) scale(1.02);
|
||||
box-shadow: 0 24px 48px rgba(116, 0, 184, 0.15);
|
||||
}
|
||||
|
||||
.projectImageContainer {
|
||||
@@ -64,11 +119,11 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.5s ease;
|
||||
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.projectCard:hover .projectImage {
|
||||
transform: scale(1.05);
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
.projectOverlay {
|
||||
@@ -77,12 +132,13 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
transition: all 0.4s ease;
|
||||
background: rgba(116, 0, 184, 0.9);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.projectCard:hover .projectOverlay {
|
||||
@@ -91,89 +147,507 @@
|
||||
|
||||
.viewButton {
|
||||
background: #fff;
|
||||
color: #6e48aa;
|
||||
color: #7400b8;
|
||||
border: none;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 12px;
|
||||
padding: 12px 24px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.viewButton:hover {
|
||||
background: #6e48aa;
|
||||
background: #7400b8;
|
||||
color: #fff;
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 20px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.categoryTag {
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 20px;
|
||||
font-weight: 600;
|
||||
padding: 6px 16px;
|
||||
font-size: 0.85rem;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
box-shadow: 0 2px 8px rgba(116, 0, 184, 0.2);
|
||||
}
|
||||
|
||||
.technologiesList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.techTag {
|
||||
margin: 0;
|
||||
color: #6e48aa;
|
||||
background: #f8fafc;
|
||||
color: #475569;
|
||||
border: 1px solid #e2e8f0;
|
||||
font-size: 0.8rem;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.techTag:hover {
|
||||
background: #7400b8;
|
||||
color: white;
|
||||
border-color: #7400b8;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.featuredBadge {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 6px 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 12px rgba(251, 191, 36, 0.3);
|
||||
}
|
||||
|
||||
.navigationControls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-top: 40px;
|
||||
gap: 20px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.navButton {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
background: white;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.navButton:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 20px rgba(116, 0, 184, 0.2);
|
||||
border-color: #7400b8;
|
||||
color: #7400b8;
|
||||
}
|
||||
|
||||
.pageIndicator {
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
font-size: 1rem;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
padding: 8px 16px;
|
||||
background: #f8fafc;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.viewAllContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 48px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.viewAllButton {
|
||||
height: 48px;
|
||||
padding: 0 32px;
|
||||
border-radius: 24px;
|
||||
font-weight: 500;
|
||||
|
||||
height: 56px;
|
||||
padding: 0 40px;
|
||||
border-radius: 28px;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
border: none;
|
||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 8px 24px rgba(116, 0, 184, 0.2);
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewAllButton::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.viewAllButton:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.viewAllButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(24, 144, 255, 0.2);
|
||||
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 32px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.projectsSection {
|
||||
padding: 60px 0;
|
||||
/* Modal Styles */
|
||||
.projectModal {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.projectModal :global(.ant-modal-content) {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 32px 64px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.projectModal :global(.ant-modal-header) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.projectModal :global(.ant-modal-body) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.closeIcon {
|
||||
font-size: 20px;
|
||||
color: #64748b;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.closeIcon:hover {
|
||||
color: #7400b8;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.modalContent {
|
||||
background: #fff;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modalHeader {
|
||||
padding: 40px 40px 30px;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.modalHeader::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.modalTitleSection {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.modalTitle {
|
||||
color: white !important;
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 800 !important;
|
||||
margin-bottom: 16px !important;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.modalCategory {
|
||||
background: rgba(255, 255, 255, 0.2) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3) !important;
|
||||
color: white !important;
|
||||
font-weight: 600;
|
||||
padding: 6px 16px;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.modalActions {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right: 40px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.actionButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.modalBody {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.projectImages {
|
||||
position: relative;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.imageCarousel {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.carouselItem {
|
||||
position: relative;
|
||||
height: 450px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modalImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.carouselItem:hover .modalImage {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.carouselDots {
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
.carouselDots :global(.ant-carousel .slick-dots li button) {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.carouselDots :global(.ant-carousel .slick-dots li.slick-active button) {
|
||||
background: #7400b8;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.projectDetails {
|
||||
padding: 40px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.detailSection {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.detailSection:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2rem !important;
|
||||
font-size: 1.6rem !important;
|
||||
font-weight: 700 !important;
|
||||
margin-bottom: 20px !important;
|
||||
color: #1e293b;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sectionTitle::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 0;
|
||||
width: 50px;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #7400b8, #6930c3);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.projectDescription {
|
||||
font-size: 1.15rem;
|
||||
line-height: 1.8;
|
||||
color: #475569;
|
||||
margin-bottom: 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.detailGrid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.featuresList {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.featureItem {
|
||||
position: relative;
|
||||
padding: 16px 0 16px 32px;
|
||||
font-size: 1.05rem;
|
||||
color: #475569;
|
||||
line-height: 1.6;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.featureItem:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.featureItem::before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 16px;
|
||||
color: #7400b8;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
background: rgba(116, 0, 184, 0.1);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.projectInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.infoItem {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
border-radius: 12px;
|
||||
border-left: 4px solid #7400b8;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.infoItem:hover {
|
||||
background: #f1f5f9;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.infoItem:last-child {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.modalTechnologies {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.modalTechTag {
|
||||
background: rgba(116, 0, 184, 0.1);
|
||||
border: 1px solid rgba(116, 0, 184, 0.2);
|
||||
color: #7400b8;
|
||||
font-weight: 600;
|
||||
border-radius: 20px;
|
||||
padding: 6px 14px;
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.modalTechTag:hover {
|
||||
background: #7400b8;
|
||||
color: white;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.projectsSection {
|
||||
padding: 80px 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2.5rem !important;
|
||||
}
|
||||
|
||||
.projectImageContainer {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.projectModal {
|
||||
margin: 16px;
|
||||
max-width: calc(100vw - 32px);
|
||||
}
|
||||
|
||||
.modalHeader {
|
||||
padding: 30px 24px 24px;
|
||||
}
|
||||
|
||||
.modalTitle {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.modalActions {
|
||||
position: static;
|
||||
margin-top: 20px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.projectDetails {
|
||||
padding: 30px 24px;
|
||||
}
|
||||
|
||||
.detailGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.carouselItem {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
height: 40px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.modalHeader {
|
||||
padding: 24px 20px 20px;
|
||||
}
|
||||
|
||||
.modalTitle {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
|
||||
.projectDetails {
|
||||
padding: 24px 20px;
|
||||
}
|
||||
|
||||
.carouselItem {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,72 @@
|
||||
/* File: src/components/TestimonialsSection/TestimonialsSection.module.css */
|
||||
.testimonialsSection {
|
||||
padding: 100px 0;
|
||||
background-color: #fff;
|
||||
padding: 120px 0;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.testimonialsSection::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="circles" width="30" height="30" patternUnits="userSpaceOnUse"><circle cx="15" cy="15" r="2" fill="%23e2e8f0" opacity="0.6"/></pattern></defs><rect width="100" height="100" fill="url(%23circles)"/></svg>');
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sectionHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 700 !important;
|
||||
margin-bottom: 16px !important;
|
||||
|
||||
font-size: 3rem !important;
|
||||
font-weight: 800 !important;
|
||||
margin-bottom: 20px !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #5e60ce 50%, #4ea8de 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
position: relative;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.sectionTitle::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 80px;
|
||||
height: 5px;
|
||||
background: linear-gradient(90deg, #7400b8, #6930c3);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 8px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.sectionSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #666;
|
||||
max-width: 600px;
|
||||
font-size: 1.2rem;
|
||||
color: #64748b;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.7;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.showcaseContainer {
|
||||
position: relative;
|
||||
padding: 20px 0;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.testimonialsCarousel {
|
||||
@@ -45,49 +75,94 @@
|
||||
}
|
||||
|
||||
.testimonialItem {
|
||||
padding: 0 15px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
height: 100%;
|
||||
border-radius: 12px;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||
border: none;
|
||||
padding: 30px;
|
||||
padding: 40px 30px;
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clientName {
|
||||
font-size: 1.2rem;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
.testimonialCard::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 30px;
|
||||
font-size: 4rem;
|
||||
color: rgba(116, 0, 184, 0.1);
|
||||
font-family: serif;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.clientTitle {
|
||||
font-size: 0.9rem;
|
||||
.testimonialCard::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 30px;
|
||||
font-size: 4rem;
|
||||
color: rgba(116, 0, 184, 0.1);
|
||||
font-family: serif;
|
||||
line-height: 1;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.testimonialCard:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: 0 20px 48px rgba(116, 0, 184, 0.15);
|
||||
}
|
||||
|
||||
.testimonialContent {
|
||||
font-size: 1rem;
|
||||
color: #555;
|
||||
line-height: 1.6;
|
||||
font-size: 1.1rem;
|
||||
color: #475569;
|
||||
line-height: 1.8;
|
||||
font-style: italic;
|
||||
margin-bottom: 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.clientName {
|
||||
font-size: 1.3rem;
|
||||
color: #1e293b;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 600;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.clientTitle {
|
||||
font-size: 0.95rem;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.projectInfo {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 24px;
|
||||
padding-top: 24px;
|
||||
border-top: 2px solid #f1f5f9;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.projectLabel {
|
||||
background: var(--primary);
|
||||
-webkit-background-clip: text; /* For Safari */
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent !important; /* Hide original text color */
|
||||
|
||||
color: transparent !important;
|
||||
font-weight: 600;
|
||||
margin-right: 8px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.technologiesList {
|
||||
@@ -99,57 +174,170 @@
|
||||
|
||||
.techTag {
|
||||
margin: 0;
|
||||
background: #f5f5f5;
|
||||
border-color: #d9d9d9;
|
||||
color: #666;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
color: #475569;
|
||||
font-size: 0.8rem;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.techTag:hover {
|
||||
background: #7400b8;
|
||||
color: white;
|
||||
border-color: #7400b8;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.filledStar {
|
||||
color: #faad14;
|
||||
color: #fbbf24;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.emptyStar {
|
||||
color: #d9d9d9;
|
||||
color: #e2e8f0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.carouselDots {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.carouselDots li button {
|
||||
background: #d9d9d9 !important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
background: #d1d5db !important;
|
||||
width: 12px !important;
|
||||
height: 12px !important;
|
||||
border-radius: 50% !important;
|
||||
transition: all 0.3s ease !important;
|
||||
}
|
||||
|
||||
.carouselDots li.slick-active button {
|
||||
background: #1890ff !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%) !important;
|
||||
transform: scale(1.2);
|
||||
box-shadow: 0 2px 8px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.viewAllContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 48px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.viewAllButton {
|
||||
height: 56px;
|
||||
padding: 0 40px;
|
||||
border-radius: 28px;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
box-shadow: 0 8px 24px rgba(116, 0, 184, 0.2);
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewAllButton::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.viewAllButton:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.viewAllButton:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 32px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
/* Enhanced Animation for Testimonial Cards */
|
||||
.testimonialCard {
|
||||
animation: fadeInUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Staggered animation for multiple cards */
|
||||
.testimonialItem:nth-child(1) .testimonialCard {
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.testimonialItem:nth-child(2) .testimonialCard {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.testimonialItem:nth-child(3) .testimonialCard {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
/* Enhanced hover effects */
|
||||
.testimonialCard:hover::before,
|
||||
.testimonialCard:hover::after {
|
||||
color: rgba(116, 0, 184, 0.2);
|
||||
transform: scale(1.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.testimonialCard:hover .clientName {
|
||||
color: #7400b8;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.testimonialsSection {
|
||||
padding: 80px 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2.5rem !important;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
padding: 30px 24px;
|
||||
}
|
||||
|
||||
.testimonialCard::before,
|
||||
.testimonialCard::after {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.testimonialContent {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.clientName {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.viewAllButton {
|
||||
height: 48px;
|
||||
padding: 0 32px;
|
||||
border-radius: 24px;
|
||||
font-weight: 500;
|
||||
|
||||
color: white;
|
||||
border: none;
|
||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.viewAllButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(24, 144, 255, 0.2);
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 480px) {
|
||||
.testimonialsSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
@@ -158,7 +346,42 @@
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.sectionSubtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
padding: 20px;
|
||||
padding: 24px 20px;
|
||||
}
|
||||
|
||||
.testimonialCard::before,
|
||||
.testimonialCard::after {
|
||||
font-size: 2.5rem;
|
||||
top: 15px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.testimonialCard::after {
|
||||
bottom: 15px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.testimonialContent {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.clientName {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.clientTitle {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.viewAllButton {
|
||||
height: 44px;
|
||||
padding: 0 28px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
32
src/app/contact/layout.tsx
Normal file
32
src/app/contact/layout.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Contact Us | Tech Master - Get In Touch for IT Solutions",
|
||||
description: "Contact Tech Master in Dubai for innovative IT solutions, digital transformation, web development, and mobile app development. Start your project today.",
|
||||
keywords: [
|
||||
"contact Tech Master",
|
||||
"Dubai IT company contact",
|
||||
"web development Dubai contact",
|
||||
"digital transformation consultation",
|
||||
"IT solutions contact",
|
||||
"mobile app development Dubai",
|
||||
"enterprise software consultation",
|
||||
"tech agency Dubai contact"
|
||||
],
|
||||
openGraph: {
|
||||
title: "Contact Us | Tech Master - Get In Touch for IT Solutions",
|
||||
description: "Contact Tech Master in Dubai for innovative IT solutions, digital transformation, and mobile app development.",
|
||||
url: "https://tech-masters.guru/contact",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/contact",
|
||||
},
|
||||
};
|
||||
|
||||
export default function ContactLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
518
src/app/contact/page.module.css
Normal file
518
src/app/contact/page.module.css
Normal file
@@ -0,0 +1,518 @@
|
||||
/* Contact Page Enhanced Styles */
|
||||
.main {
|
||||
padding-top: 80px;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.heroSection {
|
||||
position: relative;
|
||||
padding: 80px 0 60px;
|
||||
background: linear-gradient(135deg, #0F0525 0%, #1a0b3a 50%, #2A0B45 100%);
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.heroBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.heroOrb1 {
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(40px);
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.heroOrb2 {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: -150px;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(35px);
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.gradientText {
|
||||
background: linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.25rem;
|
||||
color: #cbd5e1;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 30px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.contactStats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.statItem {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.statNumber {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #a855f7;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.statLabel {
|
||||
font-size: 0.9rem;
|
||||
color: #94a3b8;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Contact Section */
|
||||
.contactSection {
|
||||
padding: 80px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.contactBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(139, 92, 246, 0.05) 0%, rgba(236, 72, 153, 0.05) 100%);
|
||||
}
|
||||
|
||||
.contactContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.contactGrid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.5fr;
|
||||
gap: 60px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* Contact Info */
|
||||
.contactInfo {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.contactInfo::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
}
|
||||
|
||||
.contactInfoHeader {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.contactInfoTitle {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.contactInfoSubtitle {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.contactInfoList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.contactInfoItem {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.contactInfoItem:hover {
|
||||
background: #f1f5f9;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.iconWrapperEmail {
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||||
}
|
||||
|
||||
.iconWrapperPhone {
|
||||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
}
|
||||
|
||||
.iconWrapperLocation {
|
||||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||
}
|
||||
|
||||
.contactIcon {
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.contactDetails {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.contactLabel {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 4px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.contactValue {
|
||||
color: #64748b;
|
||||
line-height: 1.5;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Map Section */
|
||||
.mapSection {
|
||||
margin-top: 30px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.mapContainer {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
background: linear-gradient(135deg, #e2e8f0 0%, #cbd5e1 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mapPlaceholder {
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.mapIcon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 10px;
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
/* Contact Form */
|
||||
.contactForm {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.contactForm::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
}
|
||||
|
||||
.formHeader {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.formTitle {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.formSubtitle {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.formField {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.formField :global(.ant-form-item-label) {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.formField :global(.ant-form-item-label > label) {
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.formField :global(.ant-input),
|
||||
.formField :global(.ant-input-affix-wrapper) {
|
||||
border-radius: 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
padding: 12px 16px;
|
||||
font-size: 0.95rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.formField :global(.ant-input:focus),
|
||||
.formField :global(.ant-input-affix-wrapper:focus),
|
||||
.formField :global(.ant-input-affix-wrapper-focused) {
|
||||
border-color: #8b5cf6;
|
||||
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
.formField :global(.ant-input:hover),
|
||||
.formField :global(.ant-input-affix-wrapper:hover) {
|
||||
border-color: #a855f7;
|
||||
}
|
||||
|
||||
.messageField {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.messageField :global(.ant-input) {
|
||||
resize: none;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
height: 50px;
|
||||
border-radius: 25px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border: none;
|
||||
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.submitButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 35px rgba(139, 92, 246, 0.4);
|
||||
background: linear-gradient(135deg, #7c3aed 0%, #db2777 100%);
|
||||
}
|
||||
|
||||
.submitButton:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Additional Features */
|
||||
.featuresSection {
|
||||
padding: 60px 0;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.featuresContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.featuresGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
background: #f8fafc;
|
||||
border-radius: 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.featureCard:hover {
|
||||
background: white;
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.featureIcon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto 20px;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.featureIconSupport {
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||||
}
|
||||
|
||||
.featureIconResponse {
|
||||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
}
|
||||
|
||||
.featureIconSecurity {
|
||||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.featureDescription {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1024px) {
|
||||
.contactGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.heroSection {
|
||||
padding: 60px 0 40px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.contactStats {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.contactSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.contactInfo,
|
||||
.contactForm {
|
||||
padding: 30px 20px;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.featuresGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.heroTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.contactInfo,
|
||||
.contactForm {
|
||||
padding: 25px 15px;
|
||||
}
|
||||
|
||||
.contactInfoItem {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
413
src/app/contact/page.tsx
Normal file
413
src/app/contact/page.tsx
Normal file
@@ -0,0 +1,413 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
BulbOutlined,
|
||||
ClockCircleOutlined,
|
||||
EnvironmentOutlined,
|
||||
IeOutlined,
|
||||
MailOutlined,
|
||||
PhoneOutlined,
|
||||
SendOutlined,
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Button, Form, Input, message, Typography } from "antd";
|
||||
import { motion } from "framer-motion";
|
||||
import { useState } from "react";
|
||||
import Footer from "../components/Footer/Footer";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
const { Title, Paragraph, Text } = Typography;
|
||||
const { TextArea } = Input;
|
||||
|
||||
export default function ContactPage() {
|
||||
const [form] = Form.useForm();
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setSubmitting(true);
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
message.success("Your message has been sent successfully!");
|
||||
form.resetFields();
|
||||
setSubmitting(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.5 },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
{/* Hero Section */}
|
||||
<section className={styles.heroSection}>
|
||||
<div className={styles.heroBackground}>
|
||||
<div className={styles.heroOrb1}></div>
|
||||
<div className={styles.heroOrb2}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.heroContent}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<Title level={1} className={styles.heroTitle}>
|
||||
Get In <span className={styles.gradientText}>Touch</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.heroSubtitle}>
|
||||
Ready to transform your ideas into reality? Let's start a
|
||||
conversation about your next project and how we can help bring
|
||||
your vision to life.
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.contactStats}>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>24/7</span>
|
||||
<span className={styles.statLabel}>Support</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>2hr</span>
|
||||
<span className={styles.statLabel}>Response Time</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>100%</span>
|
||||
<span className={styles.statLabel}>Secure</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact Section */}
|
||||
<section className={styles.contactSection}>
|
||||
<div className={styles.contactBackground}></div>
|
||||
<div className={styles.contactContainer}>
|
||||
<div className={styles.contactGrid}>
|
||||
{/* Contact Info */}
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.contactInfo}
|
||||
>
|
||||
<div className={styles.contactInfoHeader}>
|
||||
<Title level={3} className={styles.contactInfoTitle}>
|
||||
Contact Information
|
||||
</Title>
|
||||
<Paragraph className={styles.contactInfoSubtitle}>
|
||||
Reach out to us through any of these channels. We're here
|
||||
to help you succeed with your next project.
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
||||
<div className={styles.contactInfoList}>
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div
|
||||
className={`${styles.iconWrapper} ${styles.iconWrapperEmail}`}
|
||||
>
|
||||
<MailOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div className={styles.contactDetails}>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Email
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>
|
||||
info@techmaster.com
|
||||
</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div
|
||||
className={`${styles.iconWrapper} ${styles.iconWrapperPhone}`}
|
||||
>
|
||||
<PhoneOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div className={styles.contactDetails}>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Phone
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>
|
||||
+1 (555) 123-4567
|
||||
</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
className={styles.contactInfoItem}
|
||||
>
|
||||
<div
|
||||
className={`${styles.iconWrapper} ${styles.iconWrapperLocation}`}
|
||||
>
|
||||
<EnvironmentOutlined className={styles.contactIcon} />
|
||||
</div>
|
||||
<div className={styles.contactDetails}>
|
||||
<Text strong className={styles.contactLabel}>
|
||||
Address
|
||||
</Text>
|
||||
<Text className={styles.contactValue}>
|
||||
1234 Tech Boulevard, Innovation District
|
||||
<br />
|
||||
San Francisco, CA 94105
|
||||
</Text>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<motion.div variants={itemVariants} className={styles.mapSection}>
|
||||
<div className={styles.mapContainer}>
|
||||
<div className={styles.mapPlaceholder}>
|
||||
<EnvironmentOutlined className={styles.mapIcon} />
|
||||
<div>Interactive Map Coming Soon</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Contact Form */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.contactForm}
|
||||
>
|
||||
<div className={styles.formHeader}>
|
||||
<Title level={3} className={styles.formTitle}>
|
||||
Send Us a Message
|
||||
</Title>
|
||||
<Paragraph className={styles.formSubtitle}>
|
||||
Tell us about your project and we'll get back to you
|
||||
within 2 hours.
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={handleSubmit}
|
||||
className={styles.form}
|
||||
>
|
||||
<div className={styles.formRow}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="Full Name"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your name" },
|
||||
]}
|
||||
className={styles.formField}
|
||||
>
|
||||
<Input
|
||||
size="large"
|
||||
placeholder="Your full name"
|
||||
prefix={<UserOutlined />}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="email"
|
||||
label="Email Address"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your email" },
|
||||
{
|
||||
type: "email",
|
||||
message: "Please enter a valid email",
|
||||
},
|
||||
]}
|
||||
className={styles.formField}
|
||||
>
|
||||
<Input
|
||||
size="large"
|
||||
placeholder="your.email@example.com"
|
||||
prefix={<MailOutlined />}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
<Form.Item
|
||||
name="subject"
|
||||
label="Subject"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter a subject" },
|
||||
]}
|
||||
className={styles.formField}
|
||||
>
|
||||
<Input
|
||||
size="large"
|
||||
placeholder="How can we help you?"
|
||||
prefix={<BulbOutlined />}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="message"
|
||||
label="Message"
|
||||
rules={[
|
||||
{ required: true, message: "Please enter your message" },
|
||||
]}
|
||||
className={`${styles.formField} ${styles.messageField}`}
|
||||
>
|
||||
<TextArea
|
||||
rows={5}
|
||||
placeholder="Tell us about your project, goals, and any specific requirements..."
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
size="large"
|
||||
icon={<SendOutlined />}
|
||||
loading={submitting}
|
||||
className={styles.submitButton}
|
||||
>
|
||||
Send Message
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Section */}
|
||||
<section className={styles.featuresSection}>
|
||||
<div className={styles.featuresContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
viewport={{ once: true }}
|
||||
style={{ textAlign: "center", marginBottom: "40px" }}
|
||||
>
|
||||
<Title
|
||||
level={2}
|
||||
style={{
|
||||
fontSize: "2.5rem",
|
||||
fontWeight: 700,
|
||||
color: "#1e293b",
|
||||
marginBottom: "16px",
|
||||
}}
|
||||
>
|
||||
Why Choose{" "}
|
||||
<span
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%)",
|
||||
WebkitBackgroundClip: "text",
|
||||
WebkitTextFillColor: "transparent",
|
||||
backgroundClip: "text",
|
||||
}}
|
||||
>
|
||||
Us
|
||||
</span>
|
||||
</Title>
|
||||
<Paragraph
|
||||
style={{
|
||||
fontSize: "1.1rem",
|
||||
color: "#64748b",
|
||||
maxWidth: "600px",
|
||||
margin: "0 auto",
|
||||
}}
|
||||
>
|
||||
We're committed to providing exceptional service and support
|
||||
throughout your journey with us.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<div className={styles.featuresGrid}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.1 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.featureCard}
|
||||
>
|
||||
<div
|
||||
className={`${styles.featureIcon} ${styles.featureIconSupport}`}
|
||||
>
|
||||
<UserOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.featureTitle}>
|
||||
24/7 Support
|
||||
</Title>
|
||||
<Paragraph className={styles.featureDescription}>
|
||||
Our dedicated team is available around the clock to assist you
|
||||
with any questions or concerns.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.featureCard}
|
||||
>
|
||||
<div
|
||||
className={`${styles.featureIcon} ${styles.featureIconResponse}`}
|
||||
>
|
||||
<ClockCircleOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.featureTitle}>
|
||||
Fast Response
|
||||
</Title>
|
||||
<Paragraph className={styles.featureDescription}>
|
||||
We guarantee a response within 2 hours during business hours,
|
||||
ensuring your project moves forward quickly.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.3 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.featureCard}
|
||||
>
|
||||
<div
|
||||
className={`${styles.featureIcon} ${styles.featureIconSecurity}`}
|
||||
>
|
||||
<IeOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.featureTitle}>
|
||||
Secure & Confidential
|
||||
</Title>
|
||||
<Paragraph className={styles.featureDescription}>
|
||||
Your information is protected with enterprise-grade security and
|
||||
strict confidentiality protocols.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,35 +1,21 @@
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
--primary: linear-gradient(135deg, #6e48aa 0%, #9d50bb 100%);
|
||||
--secondary: linear-gradient(135deg, #00c1d4 0%, #ff5f6d 100%);
|
||||
--primary-glow: radial-gradient(
|
||||
circle,
|
||||
rgba(152, 71, 232, 0.2) 0%,
|
||||
rgba(71, 1, 90, 0.1) 50%,
|
||||
rgba(0, 0, 0, 0) 70%
|
||||
);
|
||||
}
|
||||
/* Color Palette */
|
||||
--french-violet: #7400b8;
|
||||
--grape: #6930c3;
|
||||
--slate-blue: #5e60ce;
|
||||
--sky-blue: #56cfe1;
|
||||
--aquamarine: #80ffdb;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
/* Gradients */
|
||||
--primary-gradient: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
--secondary-gradient: linear-gradient(135deg, #6930c3 0%, #5e60ce 100%);
|
||||
--accent-gradient: linear-gradient(135deg, #56cfe1 0%, #80ffdb 100%);
|
||||
--text-gradient: linear-gradient(135deg, #7400b8 0%, #5e60ce 100%);
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
/* Shadows */
|
||||
--primary-shadow: 0 4px 12px rgba(116, 0, 184, 0.15);
|
||||
--primary-shadow-hover: 0 8px 25px rgba(116, 0, 184, 0.25);
|
||||
--secondary-shadow: 0 2px 8px rgba(94, 96, 206, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -38,56 +24,343 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--secondary-gradient);
|
||||
}
|
||||
|
||||
/* Selection styles */
|
||||
::selection {
|
||||
background: rgba(116, 0, 184, 0.2);
|
||||
color: #7400b8;
|
||||
}
|
||||
|
||||
/* Focus styles */
|
||||
*:focus {
|
||||
outline: 2px solid #7400b8;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Button hover effects */
|
||||
.btn-primary {
|
||||
background: var(--primary-gradient);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--primary-shadow);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--primary-shadow-hover);
|
||||
}
|
||||
|
||||
/* Text gradients */
|
||||
.text-gradient {
|
||||
background: var(--text-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 24px rgba(116, 0, 184, 0.1);
|
||||
}
|
||||
|
||||
/* Animation classes */
|
||||
.fade-in {
|
||||
animation: fadeIn 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.slide-up {
|
||||
animation: slideUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
vertical-align: bottom;
|
||||
} /* ---- particles.js container ---- */
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility classes */
|
||||
.gradient-bg {
|
||||
background: var(--primary-gradient);
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: var(--text-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.shadow-primary {
|
||||
box-shadow: var(--primary-shadow);
|
||||
}
|
||||
|
||||
.shadow-primary-hover:hover {
|
||||
box-shadow: var(--primary-shadow-hover);
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
/* Color Palette */
|
||||
--french-violet: #7400b8;
|
||||
--grape: #6930c3;
|
||||
--slate-blue: #5e60ce;
|
||||
--sky-blue: #56cfe1;
|
||||
--aquamarine: #80ffdb;
|
||||
|
||||
/* Gradients */
|
||||
--primary-gradient: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
--secondary-gradient: linear-gradient(135deg, #6930c3 0%, #5e60ce 100%);
|
||||
--accent-gradient: linear-gradient(135deg, #56cfe1 0%, #80ffdb 100%);
|
||||
--text-gradient: linear-gradient(135deg, #7400b8 0%, #5e60ce 100%);
|
||||
|
||||
/* Shadows */
|
||||
--primary-shadow: 0 4px 12px rgba(116, 0, 184, 0.15);
|
||||
--primary-shadow-hover: 0 8px 25px rgba(116, 0, 184, 0.25);
|
||||
--secondary-shadow: 0 2px 8px rgba(94, 96, 206, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--secondary-gradient);
|
||||
}
|
||||
|
||||
/* Particles.js Styles */
|
||||
#particles-js {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: linear-gradient(135deg, #6e48aa 0%, #9d50bb 100%);
|
||||
z-index: 1;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.count-particles {
|
||||
background: #000022;
|
||||
position: absolute;
|
||||
top: 48px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 80px;
|
||||
color: #13e8e9;
|
||||
font-size: 0.8em;
|
||||
text-align: left;
|
||||
text-indent: 4px;
|
||||
line-height: 14px;
|
||||
padding-bottom: 2px;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
.js-count-particles {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
#stats,
|
||||
.count-particles {
|
||||
-webkit-user-select: none;
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#stats {
|
||||
border-radius: 3px 3px 0 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.count-particles {
|
||||
border-radius: 0 0 3px 3px;
|
||||
|
||||
/* Selection styles */
|
||||
::selection {
|
||||
background: rgba(116, 0, 184, 0.2);
|
||||
color: #7400b8;
|
||||
}
|
||||
|
||||
/* Focus styles */
|
||||
*:focus {
|
||||
outline: 2px solid #7400b8;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Button hover effects */
|
||||
.btn-primary {
|
||||
background: var(--primary-gradient);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--primary-shadow);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--primary-shadow-hover);
|
||||
}
|
||||
|
||||
/* Text gradients */
|
||||
.text-gradient {
|
||||
background: var(--text-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 24px rgba(116, 0, 184, 0.1);
|
||||
}
|
||||
|
||||
/* Animation classes */
|
||||
.fade-in {
|
||||
animation: fadeIn 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.slide-up {
|
||||
animation: slideUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility classes */
|
||||
.gradient-bg {
|
||||
background: var(--primary-gradient);
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: var(--text-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.shadow-primary {
|
||||
box-shadow: var(--primary-shadow);
|
||||
}
|
||||
|
||||
.shadow-primary-hover:hover {
|
||||
box-shadow: var(--primary-shadow-hover);
|
||||
}
|
||||
|
||||
@@ -7,15 +7,91 @@ import "./globals.css";
|
||||
import { themeConfig } from "./theme/themeConfig";
|
||||
|
||||
// Modern font (Inter + Orbitron backup)
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
const orbitron = {
|
||||
className: "font-orbitron",
|
||||
style:
|
||||
"@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');",
|
||||
};
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
fallback: ["system-ui", "arial"],
|
||||
adjustFontFallback: true,
|
||||
preload: true,
|
||||
variable: "--font-inter",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Tech Master | Dubai To Stars",
|
||||
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
|
||||
description:
|
||||
"Tech Master is an award-winning Dubai-based technology agency specializing in digital transformation, web development, mobile apps, AI solutions, and enterprise software. From zero to hero, we create cutting-edge digital experiences for ambitious businesses.",
|
||||
keywords: [
|
||||
"Dubai IT solutions",
|
||||
"digital transformation",
|
||||
"web development Dubai",
|
||||
"mobile app development",
|
||||
"AI solutions",
|
||||
"enterprise software",
|
||||
"ERP systems",
|
||||
"e-commerce development",
|
||||
"financial solutions",
|
||||
"legal software",
|
||||
"business intelligence",
|
||||
"cloud migration",
|
||||
"cybersecurity",
|
||||
"blockchain development",
|
||||
"IoT solutions",
|
||||
"tech agency Dubai",
|
||||
"software development UAE",
|
||||
],
|
||||
authors: [{ name: "Tech Master" }],
|
||||
creator: "Tech Master",
|
||||
publisher: "Tech Master",
|
||||
formatDetection: {
|
||||
email: false,
|
||||
address: false,
|
||||
telephone: false,
|
||||
},
|
||||
metadataBase: new URL("https://tech-masters.guru"),
|
||||
alternates: {
|
||||
canonical: "/",
|
||||
},
|
||||
openGraph: {
|
||||
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
|
||||
description:
|
||||
"Award-winning Dubai-based technology agency specializing in digital transformation, web development, mobile apps, AI solutions, and enterprise software.",
|
||||
url: "https://tech-masters.guru",
|
||||
siteName: "Tech Master",
|
||||
images: [
|
||||
{
|
||||
url: "https://tech-masters.guru/og-image.jpg",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: "Tech Master - Dubai To Stars",
|
||||
},
|
||||
],
|
||||
locale: "en_US",
|
||||
type: "website",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "Tech Master | Dubai To Stars - Award-Winning IT Solutions",
|
||||
description:
|
||||
"Award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
|
||||
images: ["https://tech-masters.guru/twitter-image.jpg"],
|
||||
creator: "@techmasterdubai",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
"max-video-preview": -1,
|
||||
"max-image-preview": "large",
|
||||
"max-snippet": -1,
|
||||
},
|
||||
},
|
||||
verification: {
|
||||
google: "your-google-verification-code",
|
||||
yandex: "your-yandex-verification-code",
|
||||
yahoo: "your-yahoo-verification-code",
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -24,19 +100,48 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang="en" className={`${inter.variable} font-sans`}>
|
||||
<head>
|
||||
{/* ThreeJS CDN */}
|
||||
<script
|
||||
src="http://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"
|
||||
src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"
|
||||
async
|
||||
></script>
|
||||
<script
|
||||
src="http://threejs.org/examples/js/libs/stats.min.js"
|
||||
src="https://threejs.org/examples/js/libs/stats.min.js"
|
||||
async
|
||||
></script>
|
||||
{/* Orbitron Font */}
|
||||
<style>{orbitron.style}</style>
|
||||
|
||||
{/* Structured Data */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Tech Master",
|
||||
url: "https://tech-masters.guru",
|
||||
logo: "https://tech-masters.guru/logo.png",
|
||||
description:
|
||||
"Award-winning Dubai-based technology agency specializing in digital transformation and innovative IT solutions.",
|
||||
address: {
|
||||
"@type": "PostalAddress",
|
||||
addressLocality: "Dubai",
|
||||
addressCountry: "UAE",
|
||||
},
|
||||
contactPoint: {
|
||||
"@type": "ContactPoint",
|
||||
telephone: "+971-XX-XXX-XXXX",
|
||||
contactType: "customer service",
|
||||
},
|
||||
sameAs: [
|
||||
"https://linkedin.com/company/tech-master",
|
||||
"https://twitter.com/techmasterdubai",
|
||||
"https://facebook.com/techmasterdubai",
|
||||
],
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
<body
|
||||
className={`${inter.className} bg-gradient-to-br from-[#0F0525] to-[#2A0B45]`}
|
||||
|
||||
@@ -6,27 +6,470 @@
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sectionHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 700 !important;
|
||||
margin-bottom: 16px !important;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #5e60ce 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sectionTitle::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #7400b8, #6930c3);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.sectionSubtitle {
|
||||
font-size: 1.1rem !important;
|
||||
color: #666 !important;
|
||||
max-width: 600px;
|
||||
margin: 0 auto !important;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
|
||||
/* Services Section */
|
||||
.servicesSection {
|
||||
padding: 100px 0;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.servicesSection::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="%23e2e8f0" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.servicesGrid {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.serviceCard {
|
||||
height: 100%;
|
||||
border-radius: 16px !important;
|
||||
overflow: hidden;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
border: none !important;
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.serviceCard::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #7400b8, #6930c3);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.serviceCard:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.serviceCard:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 40px rgba(116, 0, 184, 0.15);
|
||||
}
|
||||
|
||||
.serviceIcon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #6930c3 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.serviceCard:hover .serviceIcon {
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
box-shadow: 0 8px 20px rgba(116, 0, 184, 0.3);
|
||||
}
|
||||
|
||||
.serviceTitle {
|
||||
font-size: 1.4rem !important;
|
||||
font-weight: 600 !important;
|
||||
margin-bottom: 12px !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.serviceDescription {
|
||||
color: #666 !important;
|
||||
line-height: 1.6 !important;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.serviceFeatures {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.serviceFeatures li {
|
||||
position: relative;
|
||||
padding: 8px 0 8px 20px;
|
||||
color: #555;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.serviceFeatures li::before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 8px;
|
||||
color: #7400b8;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Statistics Section */
|
||||
.statisticsSection {
|
||||
padding: 100px 0;
|
||||
background: linear-gradient(135deg, #7400b8 0%, #5e60ce 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.statisticsSection::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>');
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.statisticsSection .sectionTitle {
|
||||
color: white !important;
|
||||
-webkit-text-fill-color: white !important;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.statisticsSection .sectionSubtitle {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
}
|
||||
|
||||
.statsGrid {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.statCard {
|
||||
text-align: center;
|
||||
padding: 30px 20px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.statCard:hover {
|
||||
transform: translateY(-5px);
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.statIcon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 16px;
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.statCard:hover .statIcon {
|
||||
transform: scale(1.1);
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.statistic {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-title) {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
font-size: 0.9rem !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-content) {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-content-value) {
|
||||
color: white !important;
|
||||
font-size: 2.5rem !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-content-suffix) {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
|
||||
.loaderContainer {
|
||||
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 {
|
||||
@@ -35,8 +478,140 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Enhanced Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.section {
|
||||
padding: 60px 16px;
|
||||
}
|
||||
|
||||
.servicesSection,
|
||||
.statisticsSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.serviceCard {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.statCard {
|
||||
padding: 20px 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-content-value) {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.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) {
|
||||
.servicesSection,
|
||||
.statisticsSection {
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
|
||||
.sectionSubtitle {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
.serviceIcon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.serviceTitle {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
|
||||
.statCard {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
|
||||
.statIcon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.statistic :global(.ant-statistic-content-value) {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
235
src/app/page.tsx
235
src/app/page.tsx
@@ -1,32 +1,42 @@
|
||||
// File: src/pages/index.tsx
|
||||
"use client";
|
||||
|
||||
import { Spin, Typography } from "antd";
|
||||
import {
|
||||
BulbOutlined,
|
||||
ClockCircleOutlined,
|
||||
CodeOutlined,
|
||||
ProjectOutlined,
|
||||
RocketOutlined,
|
||||
StarOutlined,
|
||||
TeamOutlined
|
||||
} from "@ant-design/icons";
|
||||
import { Card, Col, Row, Statistic, Typography } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import ContactSection from "./components/Contact/Contact";
|
||||
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";
|
||||
|
||||
const { Title } = Typography;
|
||||
const { Title, Paragraph } = Typography;
|
||||
|
||||
export default function Home() {
|
||||
const [showPreferences, setShowPreferences] = useState(true);
|
||||
const [userPreferences, setUserPreferences] = useState<string[]>(() => {
|
||||
try {
|
||||
const storedPreferences = localStorage.getItem("userPreferences");
|
||||
return storedPreferences ? JSON.parse(storedPreferences) : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
const [showPreferences, setShowPreferences] = useState(
|
||||
() => userPreferences.length === 0,
|
||||
);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [userPreferences, setUserPreferences] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if preferences already exist in localStorage
|
||||
const storedPreferences = localStorage.getItem("userPreferences");
|
||||
|
||||
if (storedPreferences) {
|
||||
setUserPreferences(JSON.parse(storedPreferences));
|
||||
setShowPreferences(false);
|
||||
}
|
||||
|
||||
// Simulate loading of resources
|
||||
const timer = setTimeout(() => {
|
||||
setLoading(false);
|
||||
@@ -46,10 +56,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>
|
||||
);
|
||||
}
|
||||
@@ -61,12 +101,169 @@ export default function Home() {
|
||||
)}
|
||||
|
||||
<main className={styles.main}>
|
||||
<section id="home">
|
||||
<HeroSection />
|
||||
<ServicesSection userPreferences={userPreferences} />
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section id="services" className={styles.servicesSection}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Title level={2} className={styles.sectionTitle}>
|
||||
Our Services
|
||||
</Title>
|
||||
<Paragraph className={styles.sectionSubtitle}>
|
||||
We offer comprehensive solutions to transform your digital presence and drive business growth
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
||||
<Row gutter={[32, 32]} className={styles.servicesGrid}>
|
||||
<Col xs={24} sm={12} lg={8}>
|
||||
<Card className={styles.serviceCard} hoverable>
|
||||
<div className={styles.serviceIcon}>
|
||||
<CodeOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.serviceTitle}>
|
||||
Web Development
|
||||
</Title>
|
||||
<Paragraph className={styles.serviceDescription}>
|
||||
Custom web applications built with modern technologies and best practices for optimal performance and user experience.
|
||||
</Paragraph>
|
||||
<ul className={styles.serviceFeatures}>
|
||||
<li>Responsive Design</li>
|
||||
<li>SEO Optimization</li>
|
||||
<li>Performance Tuning</li>
|
||||
<li>Security Implementation</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} lg={8}>
|
||||
<Card className={styles.serviceCard} hoverable>
|
||||
<div className={styles.serviceIcon}>
|
||||
<RocketOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.serviceTitle}>
|
||||
Mobile Development
|
||||
</Title>
|
||||
<Paragraph className={styles.serviceDescription}>
|
||||
Native and cross-platform mobile applications that deliver exceptional user experiences across all devices.
|
||||
</Paragraph>
|
||||
<ul className={styles.serviceFeatures}>
|
||||
<li>iOS & Android Apps</li>
|
||||
<li>Cross-platform Solutions</li>
|
||||
<li>App Store Optimization</li>
|
||||
<li>Push Notifications</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} lg={8}>
|
||||
<Card className={styles.serviceCard} hoverable>
|
||||
<div className={styles.serviceIcon}>
|
||||
<BulbOutlined />
|
||||
</div>
|
||||
<Title level={4} className={styles.serviceTitle}>
|
||||
UI/UX Design
|
||||
</Title>
|
||||
<Paragraph className={styles.serviceDescription}>
|
||||
User-centered design solutions that create intuitive, engaging, and conversion-focused digital experiences.
|
||||
</Paragraph>
|
||||
<ul className={styles.serviceFeatures}>
|
||||
<li>User Research</li>
|
||||
<li>Wireframing & Prototyping</li>
|
||||
<li>Visual Design</li>
|
||||
<li>Usability Testing</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Statistics Section */}
|
||||
<section id="statistics" className={styles.statisticsSection}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Title level={2} className={styles.sectionTitle}>
|
||||
Our Impact
|
||||
</Title>
|
||||
<Paragraph className={styles.sectionSubtitle}>
|
||||
Numbers that speak for themselves - our commitment to excellence in every project
|
||||
</Paragraph>
|
||||
</div>
|
||||
|
||||
<Row gutter={[48, 32]} className={styles.statsGrid}>
|
||||
<Col xs={12} sm={6}>
|
||||
<div className={styles.statCard}>
|
||||
<div className={styles.statIcon}>
|
||||
<ProjectOutlined />
|
||||
</div>
|
||||
<Statistic
|
||||
title="Projects Completed"
|
||||
value={150}
|
||||
suffix="+"
|
||||
className={styles.statistic}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<Col xs={12} sm={6}>
|
||||
<div className={styles.statCard}>
|
||||
<div className={styles.statIcon}>
|
||||
<TeamOutlined />
|
||||
</div>
|
||||
<Statistic
|
||||
title="Happy Clients"
|
||||
value={80}
|
||||
suffix="+"
|
||||
className={styles.statistic}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<Col xs={12} sm={6}>
|
||||
<div className={styles.statCard}>
|
||||
<div className={styles.statIcon}>
|
||||
<StarOutlined />
|
||||
</div>
|
||||
<Statistic
|
||||
title="Average Rating"
|
||||
value={4.9}
|
||||
suffix="/5"
|
||||
precision={1}
|
||||
className={styles.statistic}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<Col xs={12} sm={6}>
|
||||
<div className={styles.statCard}>
|
||||
<div className={styles.statIcon}>
|
||||
<ClockCircleOutlined />
|
||||
</div>
|
||||
<Statistic
|
||||
title="Years Experience"
|
||||
value={8}
|
||||
suffix="+"
|
||||
className={styles.statistic}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="projects">
|
||||
<ProjectsShowcase />
|
||||
</section>
|
||||
|
||||
<section id="testimonials">
|
||||
<TestimonialsSection />
|
||||
<ContactSection />
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
34
src/app/projects/layout.tsx
Normal file
34
src/app/projects/layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Our Projects | Tech Master - Portfolio of Digital Solutions",
|
||||
description: "Explore our portfolio of successful projects including ERP systems, e-commerce platforms, payment solutions, legal software, and business intelligence dashboards developed in Dubai.",
|
||||
keywords: [
|
||||
"portfolio projects",
|
||||
"ERP systems Dubai",
|
||||
"e-commerce development",
|
||||
"payment platforms",
|
||||
"legal software",
|
||||
"business intelligence",
|
||||
"web applications",
|
||||
"mobile apps",
|
||||
"enterprise software",
|
||||
"fintech solutions"
|
||||
],
|
||||
openGraph: {
|
||||
title: "Our Projects | Tech Master - Portfolio of Digital Solutions",
|
||||
description: "Portfolio of successful projects including ERP systems, e-commerce platforms, payment solutions, and business intelligence dashboards.",
|
||||
url: "https://tech-masters.guru/projects",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/projects",
|
||||
},
|
||||
};
|
||||
|
||||
export default function ProjectsLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
408
src/app/projects/page.module.css
Normal file
408
src/app/projects/page.module.css
Normal file
@@ -0,0 +1,408 @@
|
||||
/* Projects Page Styles */
|
||||
.main {
|
||||
padding-top: 80px;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.heroSection {
|
||||
position: relative;
|
||||
padding: 80px 0 60px;
|
||||
background: linear-gradient(135deg, #0F0525 0%, #1a0b3a 50%, #2A0B45 100%);
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.heroBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.heroOrb1 {
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(40px);
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.heroOrb2 {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: -150px;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(35px);
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.gradientText {
|
||||
background: linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.25rem;
|
||||
color: #cbd5e1;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 30px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.projectStats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.statItem {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.statNumber {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #a855f7;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.statLabel {
|
||||
font-size: 0.9rem;
|
||||
color: #94a3b8;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Projects Section */
|
||||
.projectsSection {
|
||||
padding: 80px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.projectsBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(139, 92, 246, 0.05) 0%, rgba(236, 72, 153, 0.05) 100%);
|
||||
}
|
||||
|
||||
.projectsContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.projectsHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.projectsTitle {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.projectsSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #64748b;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Filter Section */
|
||||
.filterSection {
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.filterButtons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filterButton {
|
||||
padding: 8px 20px;
|
||||
border-radius: 25px;
|
||||
border: 2px solid #e5e7eb;
|
||||
background: white;
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filterButton:hover {
|
||||
border-color: #8b5cf6;
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.filterButton.active {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-color: transparent;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Projects Grid */
|
||||
.projectsGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.projectCard {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.projectCard:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.projectImageContainer {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.projectImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.projectCard:hover .projectImage {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.projectOverlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.projectCard:hover .projectOverlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.viewButton {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border: none;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.featuredBadge {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.projectContent {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.categoryTag {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.projectTitle {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.projectDescription {
|
||||
color: #64748b;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 12px;
|
||||
font-size: 0.85rem;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.technologiesList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.techTag {
|
||||
background: #f8fafc;
|
||||
color: #475569;
|
||||
border: 1px solid #e2e8f0;
|
||||
font-size: 0.75rem;
|
||||
padding: 2px 6px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.projectMeta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #f1f5f9;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.projectDuration {
|
||||
font-size: 0.75rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.projectTeam {
|
||||
font-size: 0.75rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
/* Load More Section */
|
||||
.loadMoreSection {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.loadMoreButton {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 32px;
|
||||
border-radius: 25px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.loadMoreButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
||||
background: linear-gradient(135deg, #7c3aed 0%, #db2777 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1024px) {
|
||||
.projectsGrid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.heroSection {
|
||||
padding: 60px 0 40px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.projectStats {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.projectsSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.projectsGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.filterButtons {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filterButton {
|
||||
padding: 6px 16px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.heroTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.projectCard {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.projectContent {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
640
src/app/projects/page.tsx
Normal file
640
src/app/projects/page.tsx
Normal file
@@ -0,0 +1,640 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
CloseOutlined,
|
||||
EyeOutlined,
|
||||
LinkOutlined,
|
||||
RocketOutlined,
|
||||
UserOutlined
|
||||
} from "@ant-design/icons";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Card,
|
||||
Carousel,
|
||||
Col,
|
||||
Modal,
|
||||
Row,
|
||||
Tag,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import Footer from "../components/Footer/Footer";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
const { Title, Paragraph, Text } = Typography;
|
||||
|
||||
interface Project {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
imageUrl: string;
|
||||
category: string;
|
||||
technologies: string[];
|
||||
featured: boolean;
|
||||
detailedDescription: string;
|
||||
images: string[];
|
||||
liveUrl?: string;
|
||||
githubUrl?: string;
|
||||
features: string[];
|
||||
duration: string;
|
||||
teamSize: string;
|
||||
}
|
||||
|
||||
// Sample project data (same as in ProjectsShowcase)
|
||||
const projectsData: Project[] = [
|
||||
{
|
||||
id: "p1",
|
||||
title: "BPro ERP System",
|
||||
description:
|
||||
"Comprehensive enterprise resource planning system with advanced business process management and real-time analytics.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
category: "Enterprise Software",
|
||||
technologies: ["React", "Node.js", "PostgreSQL", "Redis"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A comprehensive ERP system designed for modern businesses, featuring advanced business process management, real-time analytics, and seamless integration with existing enterprise systems. The platform streamlines operations across all departments.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
"https://tech-masters.guru/photos/projects/bpro-erp.jpg",
|
||||
],
|
||||
liveUrl: "https://bpro-erp.com",
|
||||
githubUrl: "https://github.com/company/bpro-erp",
|
||||
features: [
|
||||
"Advanced business process management",
|
||||
"Real-time analytics and reporting",
|
||||
"Multi-department integration",
|
||||
"Custom workflow automation",
|
||||
"Comprehensive audit trails",
|
||||
],
|
||||
duration: "8 months",
|
||||
teamSize: "12 developers",
|
||||
},
|
||||
{
|
||||
id: "p2",
|
||||
title: "Law Office Management",
|
||||
description:
|
||||
"Complete legal practice management solution with case tracking, document management, and client portal.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
category: "Legal Software",
|
||||
technologies: ["Angular", ".NET Core", "SQL Server", "Azure"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A comprehensive legal practice management system designed to streamline law office operations, manage cases, track billable hours, and provide secure client communication portals.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
"https://tech-masters.guru/photos/projects/law-office-login.png",
|
||||
"https://tech-masters.guru/photos/projects/law-office-home.png",
|
||||
],
|
||||
liveUrl: "https://law-office-demo.com",
|
||||
githubUrl: "https://github.com/company/law-office-system",
|
||||
features: [
|
||||
"Case management and tracking",
|
||||
"Document management system",
|
||||
"Client portal and communication",
|
||||
"Time tracking and billing",
|
||||
"Calendar and appointment management",
|
||||
],
|
||||
duration: "6 months",
|
||||
teamSize: "8 developers",
|
||||
},
|
||||
{
|
||||
id: "p3",
|
||||
title: "MoneyOut Payment Platform",
|
||||
description:
|
||||
"Secure digital payment processing platform with multi-currency support and advanced fraud detection.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
category: "FinTech",
|
||||
technologies: ["Next.js", "Stripe", "MongoDB", "GraphQL"],
|
||||
featured: true,
|
||||
detailedDescription:
|
||||
"A modern payment processing platform that enables secure digital transactions with multi-currency support, advanced fraud detection, and comprehensive merchant tools.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
"https://tech-masters.guru/photos/projects/moneyout.png",
|
||||
],
|
||||
liveUrl: "https://moneyout-demo.com",
|
||||
githubUrl: "https://github.com/company/moneyout-platform",
|
||||
features: [
|
||||
"Multi-currency payment processing",
|
||||
"Advanced fraud detection",
|
||||
"Merchant dashboard and analytics",
|
||||
"Secure API integration",
|
||||
"Real-time transaction monitoring",
|
||||
],
|
||||
duration: "7 months",
|
||||
teamSize: "10 developers",
|
||||
},
|
||||
{
|
||||
id: "p4",
|
||||
title: "Cloths E-commerce Platform",
|
||||
description:
|
||||
"Modern fashion e-commerce platform with advanced product catalog, virtual try-on, and personalized recommendations.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
category: "E-commerce",
|
||||
technologies: ["React", "Node.js", "MongoDB", "AWS"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A cutting-edge fashion e-commerce platform featuring virtual try-on technology, personalized recommendations, and seamless mobile shopping experience.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
"https://tech-masters.guru/photos/projects/cloths-e-commerce.png",
|
||||
],
|
||||
liveUrl: "https://cloths-ecommerce.com",
|
||||
githubUrl: "https://github.com/company/cloths-ecommerce",
|
||||
features: [
|
||||
"Virtual try-on technology",
|
||||
"Personalized recommendations",
|
||||
"Advanced product catalog",
|
||||
"Mobile-first design",
|
||||
"Social commerce integration",
|
||||
],
|
||||
duration: "5 months",
|
||||
teamSize: "6 developers",
|
||||
},
|
||||
{
|
||||
id: "p5",
|
||||
title: "Nanas Dashboard",
|
||||
description:
|
||||
"Comprehensive business intelligence dashboard with real-time data visualization and predictive analytics.",
|
||||
imageUrl:
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
category: "Business Intelligence",
|
||||
technologies: ["Vue.js", "Python", "PostgreSQL", "Docker"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A powerful business intelligence dashboard that provides real-time data visualization, predictive analytics, and comprehensive reporting for data-driven decision making.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
"https://tech-masters.guru/photos/projects/nanas-main-dashboard.png",
|
||||
],
|
||||
liveUrl: "https://nanas-dashboard.com",
|
||||
githubUrl: "https://github.com/company/nanas-dashboard",
|
||||
features: [
|
||||
"Real-time data visualization",
|
||||
"Predictive analytics",
|
||||
"Custom reporting tools",
|
||||
"Interactive dashboards",
|
||||
"Data export capabilities",
|
||||
],
|
||||
duration: "4 months",
|
||||
teamSize: "5 developers",
|
||||
},
|
||||
{
|
||||
id: "p6",
|
||||
title: "Easy Pay Login System",
|
||||
description:
|
||||
"Secure authentication system with multi-factor authentication and advanced security features for financial applications.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
category: "Security",
|
||||
technologies: ["React", "Node.js", "JWT", "Redis"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A robust authentication system designed for financial applications, featuring multi-factor authentication, advanced security protocols, and seamless user experience.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
"https://tech-masters.guru/photos/projects/easy-pay-login.png",
|
||||
],
|
||||
liveUrl: "https://easy-pay-login.com",
|
||||
githubUrl: "https://github.com/company/easy-pay-login",
|
||||
features: [
|
||||
"Multi-factor authentication",
|
||||
"Advanced security protocols",
|
||||
"Session management",
|
||||
"Audit logging",
|
||||
"Password recovery system",
|
||||
],
|
||||
duration: "3 months",
|
||||
teamSize: "4 developers",
|
||||
},
|
||||
{
|
||||
id: "p7",
|
||||
title: "Majsin Dashboard",
|
||||
description:
|
||||
"Advanced analytics dashboard with machine learning insights and customizable reporting for enterprise clients.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
category: "Analytics",
|
||||
technologies: ["Angular", "Python", "TensorFlow", "AWS"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"An advanced analytics dashboard powered by machine learning, providing deep insights and customizable reporting for enterprise-level decision making.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
"https://tech-masters.guru/photos/projects/majsin-dashborad.png",
|
||||
],
|
||||
liveUrl: "https://majsin-dashboard.com",
|
||||
githubUrl: "https://github.com/company/majsin-dashboard",
|
||||
features: [
|
||||
"Machine learning insights",
|
||||
"Customizable reporting",
|
||||
"Real-time data processing",
|
||||
"Advanced visualizations",
|
||||
"API integration capabilities",
|
||||
],
|
||||
duration: "6 months",
|
||||
teamSize: "7 developers",
|
||||
},
|
||||
{
|
||||
id: "p8",
|
||||
title: "SVU Hardware Management",
|
||||
description:
|
||||
"Comprehensive hardware inventory and management system for educational institutions with asset tracking.",
|
||||
imageUrl: "https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
category: "Education",
|
||||
technologies: ["React", "Node.js", "MySQL", "Docker"],
|
||||
featured: false,
|
||||
detailedDescription:
|
||||
"A comprehensive hardware management system designed for educational institutions, featuring asset tracking, maintenance scheduling, and detailed reporting capabilities.",
|
||||
images: [
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
"https://tech-masters.guru/photos/projects/svu-hw.png",
|
||||
],
|
||||
liveUrl: "https://svu-hardware.com",
|
||||
githubUrl: "https://github.com/company/svu-hardware",
|
||||
features: [
|
||||
"Asset tracking and management",
|
||||
"Maintenance scheduling",
|
||||
"Inventory control",
|
||||
"Detailed reporting",
|
||||
"User access management",
|
||||
],
|
||||
duration: "5 months",
|
||||
teamSize: "6 developers",
|
||||
},
|
||||
];
|
||||
|
||||
const categories = [
|
||||
"All",
|
||||
"Enterprise Software",
|
||||
"Legal Software",
|
||||
"FinTech",
|
||||
"E-commerce",
|
||||
"Business Intelligence",
|
||||
"Security",
|
||||
"Analytics",
|
||||
"Education",
|
||||
];
|
||||
|
||||
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(9);
|
||||
|
||||
const filteredProjects =
|
||||
selectedCategory === "All"
|
||||
? projectsData
|
||||
: projectsData.filter((project) => project.category === selectedCategory);
|
||||
|
||||
const displayedProjects = filteredProjects.slice(0, visibleProjects);
|
||||
|
||||
const handleProjectClick = (project: Project) => {
|
||||
setSelectedProject(project);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleModalClose = () => {
|
||||
setIsModalVisible(false);
|
||||
setTimeout(() => {
|
||||
setSelectedProject(null);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const handleLoadMore = () => {
|
||||
setVisibleProjects((prev) => Math.min(prev + 6, filteredProjects.length));
|
||||
};
|
||||
|
||||
const handleCategoryClick = (category: string) => {
|
||||
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 = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: { duration: 0.5 },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
{/* Hero Section */}
|
||||
<section className={styles.heroSection}>
|
||||
<div className={styles.heroBackground}>
|
||||
<div className={styles.heroOrb1}></div>
|
||||
<div className={styles.heroOrb2}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.heroContent}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<Title level={1} className={styles.heroTitle}>
|
||||
Our <span className={styles.gradientText}>Projects</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.heroSubtitle}>
|
||||
Explore our portfolio of innovative solutions that have
|
||||
transformed businesses and delivered exceptional results across
|
||||
various industries.
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.projectStats}>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>50+</span>
|
||||
<span className={styles.statLabel}>Projects Completed</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>8</span>
|
||||
<span className={styles.statLabel}>Industries Served</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>100%</span>
|
||||
<span className={styles.statLabel}>Client Satisfaction</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Projects Section */}
|
||||
<section className={styles.projectsSection}>
|
||||
<div className={styles.projectsBackground}></div>
|
||||
<div className={styles.projectsContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.projectsHeader}
|
||||
>
|
||||
<Title level={2} className={styles.projectsTitle}>
|
||||
Featured <span className={styles.gradientText}>Work</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.projectsSubtitle}>
|
||||
Discover our latest projects and see how we've helped businesses
|
||||
achieve their digital transformation goals.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
{/* Filter Section */}
|
||||
<div className={styles.filterSection}>
|
||||
<div className={styles.filterButtons}>
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
key={category}
|
||||
className={`${styles.filterButton} ${
|
||||
selectedCategory === category ? styles.active : ""
|
||||
}`}
|
||||
onClick={() => handleCategoryClick(category)}
|
||||
>
|
||||
{category}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Projects Grid */}
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.projectsGrid}
|
||||
>
|
||||
{displayedProjects.map((project) => (
|
||||
<motion.div key={project.id} variants={itemVariants}>
|
||||
<Card
|
||||
hoverable
|
||||
onClick={() => handleProjectClick(project)}
|
||||
className={styles.projectCard}
|
||||
cover={
|
||||
<div className={styles.projectImageContainer}>
|
||||
<Image
|
||||
alt={project.title}
|
||||
src={project.imageUrl}
|
||||
className={styles.projectImage}
|
||||
width={400}
|
||||
height={250}
|
||||
/>
|
||||
<div className={styles.projectOverlay}>
|
||||
<Button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon={<EyeOutlined />}
|
||||
className={styles.viewButton}
|
||||
/>
|
||||
</div>
|
||||
{project.featured && (
|
||||
<Badge.Ribbon
|
||||
text="Featured"
|
||||
className={styles.featuredBadge}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={styles.projectContent}>
|
||||
<div className={styles.categoryTag}>
|
||||
<Tag color="blue">{project.category}</Tag>
|
||||
</div>
|
||||
<Title level={4} className={styles.projectTitle}>
|
||||
{project.title}
|
||||
</Title>
|
||||
<Paragraph className={styles.projectDescription}>
|
||||
{project.description}
|
||||
</Paragraph>
|
||||
<div className={styles.technologiesList}>
|
||||
{project.technologies.slice(0, 4).map((tech) => (
|
||||
<Tag key={tech} className={styles.techTag}>
|
||||
{tech}
|
||||
</Tag>
|
||||
))}
|
||||
{project.technologies.length > 4 && (
|
||||
<Tag className={styles.techTag}>
|
||||
+{project.technologies.length - 4} more
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.projectMeta}>
|
||||
<div className={styles.projectDuration}>
|
||||
<RocketOutlined /> {project.duration}
|
||||
</div>
|
||||
<div className={styles.projectTeam}>
|
||||
<UserOutlined /> {project.teamSize}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
{/* Load More Section */}
|
||||
{visibleProjects < filteredProjects.length && (
|
||||
<div className={styles.loadMoreSection}>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
onClick={handleLoadMore}
|
||||
className={styles.loadMoreButton}
|
||||
>
|
||||
Load More Projects
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Project Details Modal */}
|
||||
<AnimatePresence>
|
||||
{isModalVisible && selectedProject && (
|
||||
<Modal
|
||||
open={isModalVisible}
|
||||
onCancel={handleModalClose}
|
||||
footer={null}
|
||||
width={1000}
|
||||
className={styles.projectModal}
|
||||
closeIcon={<CloseOutlined />}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.8 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<div style={{ padding: "20px 0" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "flex-start",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Title level={2} style={{ marginBottom: "8px" }}>
|
||||
{selectedProject.title}
|
||||
</Title>
|
||||
<Tag color="blue">{selectedProject.category}</Tag>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "12px" }}>
|
||||
{selectedProject.liveUrl && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<LinkOutlined />}
|
||||
href={selectedProject.liveUrl}
|
||||
target="_blank"
|
||||
>
|
||||
Live Demo
|
||||
</Button>
|
||||
)}
|
||||
{/* {selectedProject.githubUrl && (
|
||||
<Button
|
||||
icon={<GithubOutlined />}
|
||||
href={selectedProject.githubUrl}
|
||||
target="_blank"
|
||||
>
|
||||
View Code
|
||||
</Button>
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: "24px" }}>
|
||||
<Carousel autoplay dots={{ className: "custom-dots" }}>
|
||||
{selectedProject.images.map((image, index) => (
|
||||
<div key={index}>
|
||||
<Image
|
||||
src={image}
|
||||
alt={`${selectedProject.title} - Image ${index + 1}`}
|
||||
width={800}
|
||||
height={400}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "auto",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</Carousel>
|
||||
</div>
|
||||
|
||||
<Row gutter={[24, 24]}>
|
||||
<Col xs={24} md={12}>
|
||||
<Title level={4}>Project Overview</Title>
|
||||
<Paragraph>{selectedProject.detailedDescription}</Paragraph>
|
||||
|
||||
<Title level={4} style={{ marginTop: "24px" }}>
|
||||
Key Features
|
||||
</Title>
|
||||
<ul>
|
||||
{selectedProject.features.map((feature, index) => (
|
||||
<li key={index} style={{ marginBottom: "8px" }}>
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Col>
|
||||
<Col xs={24} md={12}>
|
||||
<Title level={4}>Project Details</Title>
|
||||
<div style={{ marginBottom: "16px" }}>
|
||||
<Text strong>Duration:</Text> {selectedProject.duration}
|
||||
</div>
|
||||
<div style={{ marginBottom: "16px" }}>
|
||||
<Text strong>Team Size:</Text> {selectedProject.teamSize}
|
||||
</div>
|
||||
<div style={{ marginBottom: "16px" }}>
|
||||
<Text strong>Technologies:</Text>
|
||||
<div style={{ marginTop: "8px" }}>
|
||||
{selectedProject.technologies.map((tech) => (
|
||||
<Tag key={tech} style={{ marginBottom: "4px" }}>
|
||||
{tech}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</motion.div>
|
||||
</Modal>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
12
src/app/robots.ts
Normal file
12
src/app/robots.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { MetadataRoute } from 'next'
|
||||
|
||||
export default function robots(): MetadataRoute.Robots {
|
||||
return {
|
||||
rules: {
|
||||
userAgent: '*',
|
||||
allow: '/',
|
||||
disallow: '/private/',
|
||||
},
|
||||
sitemap: 'https://tech-masters.guru/sitemap.xml',
|
||||
}
|
||||
}
|
||||
35
src/app/services/layout.tsx
Normal file
35
src/app/services/layout.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Our Services | Tech Master - Digital Transformation & IT Solutions",
|
||||
description:
|
||||
"Explore our comprehensive IT services including web development, mobile apps, AI solutions, ERP systems, e-commerce platforms, and digital transformation services in Dubai.",
|
||||
keywords: [
|
||||
"web development Dubai",
|
||||
"mobile app development",
|
||||
"AI solutions",
|
||||
"ERP systems",
|
||||
"e-commerce development",
|
||||
"digital transformation",
|
||||
"cloud migration",
|
||||
"cybersecurity services",
|
||||
"IT consulting Dubai",
|
||||
],
|
||||
openGraph: {
|
||||
title: "Our Services | Tech Master - Digital Transformation & IT Solutions",
|
||||
description:
|
||||
"Comprehensive IT services including web development, mobile apps, AI solutions, ERP systems, and digital transformation in Dubai.",
|
||||
url: "https://tech-masters.guru/services",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/services",
|
||||
},
|
||||
};
|
||||
|
||||
export default function ServicesLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
723
src/app/services/page.module.css
Normal file
723
src/app/services/page.module.css
Normal file
@@ -0,0 +1,723 @@
|
||||
/* Services Page Enhanced Styles */
|
||||
.main {
|
||||
padding-top: 80px;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.heroSection {
|
||||
position: relative;
|
||||
padding: 80px 0 60px;
|
||||
background: linear-gradient(135deg, #0f0525 0%, #1a0b3a 50%, #2a0b45 100%);
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.heroBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.heroOrb1 {
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(40px);
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.heroOrb2 {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: -150px;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||
border-radius: 50%;
|
||||
filter: blur(35px);
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.gradientText {
|
||||
background: linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.25rem;
|
||||
color: #cbd5e1;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 30px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.serviceStats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.statItem {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.statNumber {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #a855f7;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.statLabel {
|
||||
font-size: 0.9rem;
|
||||
color: #94a3b8;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Hero Footer */
|
||||
.heroFooter {
|
||||
margin-top: 60px;
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.heroFooterContent {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.footerColumn {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footerColumnTitle {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.footerColumnIcon {
|
||||
color: #a855f7;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.footerLinks {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footerLink {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.footerLink a {
|
||||
color: #cbd5e1;
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.footerLink a:hover {
|
||||
color: #a855f7;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.footerLinkIcon {
|
||||
font-size: 0.8rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.footerBottom {
|
||||
text-align: center;
|
||||
padding-top: 30px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.footerBottomText {
|
||||
color: #94a3b8;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.socialLink:hover {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
transform: translateY(-2px);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
color: #64748b;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
/* Services Section */
|
||||
.servicesSection {
|
||||
padding: 80px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.servicesBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(139, 92, 246, 0.05) 0%,
|
||||
rgba(236, 72, 153, 0.05) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.servicesContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.servicesHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.servicesTitle {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.servicesSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #64748b;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.servicesGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 30px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
/* Service Cards */
|
||||
.serviceCard {
|
||||
background: white;
|
||||
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 {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
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(-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: 70px;
|
||||
height: 70px;
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.serviceCard:hover .serviceIconWrapper {
|
||||
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 {
|
||||
font-size: 32px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Service Icon Colors */
|
||||
.iconWebDev {
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||||
}
|
||||
|
||||
.iconBranding {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
|
||||
}
|
||||
|
||||
.iconEcommerce {
|
||||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
}
|
||||
|
||||
.iconSEO {
|
||||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||
}
|
||||
|
||||
.iconMobile {
|
||||
background: linear-gradient(135deg, #ec4899 0%, #db2777 100%);
|
||||
}
|
||||
|
||||
.iconCloud {
|
||||
background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);
|
||||
}
|
||||
|
||||
.iconAI {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
|
||||
}
|
||||
|
||||
.iconConsulting {
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
padding: 0 32px 32px;
|
||||
}
|
||||
|
||||
.serviceTitle {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.serviceDescription {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
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;
|
||||
}
|
||||
|
||||
.serviceFeature {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #64748b;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 10px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.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: 10px 20px;
|
||||
border-radius: 20px;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.learnMoreBtn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3);
|
||||
background: linear-gradient(135deg, #7c3aed 0%, #db2777 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Process Section */
|
||||
.processSection {
|
||||
padding: 80px 0;
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.processBackground {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
||||
}
|
||||
|
||||
.processContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.processHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.processTitle {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.processSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #64748b;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.processSteps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 30px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.processStep {
|
||||
text-align: center;
|
||||
padding: 30px 20px;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.processStep:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.stepNumber {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 20px;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stepTitle {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.stepDescription {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* CTA Section */
|
||||
.ctaSection {
|
||||
padding: 80px 0;
|
||||
background: linear-gradient(135deg, #0f0525 0%, #1a0b3a 50%, #2a0b45 100%);
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ctaSubtitle {
|
||||
font-size: 1.1rem;
|
||||
color: #cbd5e1;
|
||||
margin-bottom: 40px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 16px 32px;
|
||||
border-radius: 30px;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ctaButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 35px rgba(139, 92, 246, 0.4);
|
||||
background: linear-gradient(135deg, #7c3aed 0%, #db2777 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1024px) {
|
||||
.servicesGrid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.processSteps {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.heroSection {
|
||||
padding: 60px 0 40px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.serviceStats {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.heroFooterContent {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.footerColumn {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.socialLinks {
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.servicesSection {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.servicesGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.serviceCard {
|
||||
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 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.heroTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.serviceCard {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.cardHeader {
|
||||
padding: 20px 16px 16px;
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
padding: 0 16px 20px;
|
||||
}
|
||||
|
||||
.serviceIconWrapper {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.serviceIcon {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.servicesTitle,
|
||||
.processTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
382
src/app/services/page.tsx
Normal file
382
src/app/services/page.tsx
Normal file
@@ -0,0 +1,382 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ArrowRightOutlined,
|
||||
CloudOutlined,
|
||||
CodeOutlined,
|
||||
GlobalOutlined,
|
||||
LineChartOutlined,
|
||||
MobileOutlined,
|
||||
RobotOutlined,
|
||||
RocketOutlined,
|
||||
ShoppingOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Button, Typography } from "antd";
|
||||
import { motion } from "framer-motion";
|
||||
import React from "react";
|
||||
import Footer from "../components/Footer/Footer";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
const { Title, Paragraph } = Typography;
|
||||
|
||||
interface Service {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
iconClass: string;
|
||||
features: string[];
|
||||
preferenceMatches: string[];
|
||||
}
|
||||
|
||||
const allServices: Service[] = [
|
||||
{
|
||||
id: "webdev",
|
||||
title: "Web Development",
|
||||
description:
|
||||
"Custom web applications with cutting-edge technologies and responsive design.",
|
||||
icon: <CodeOutlined />,
|
||||
iconClass: styles.iconWebDev,
|
||||
features: [
|
||||
"React & Next.js",
|
||||
"Node.js Backend",
|
||||
"Responsive Design",
|
||||
"Performance Optimization",
|
||||
],
|
||||
preferenceMatches: ["ecommerce", "cloud", "seo"],
|
||||
},
|
||||
{
|
||||
id: "branding",
|
||||
title: "Branding & Identity",
|
||||
description:
|
||||
"Complete brand identity packages including logos, guidelines, and visual systems.",
|
||||
icon: <RocketOutlined />,
|
||||
iconClass: styles.iconBranding,
|
||||
features: [
|
||||
"Logo Design",
|
||||
"Brand Guidelines",
|
||||
"Visual Identity",
|
||||
"Marketing Materials",
|
||||
],
|
||||
preferenceMatches: ["branding", "seo"],
|
||||
},
|
||||
{
|
||||
id: "ecom",
|
||||
title: "E-commerce Solutions",
|
||||
description:
|
||||
"Full-stack e-commerce platforms with secure payment integration and inventory management.",
|
||||
icon: <ShoppingOutlined />,
|
||||
iconClass: styles.iconEcommerce,
|
||||
features: [
|
||||
"Payment Integration",
|
||||
"Inventory Management",
|
||||
"Order Processing",
|
||||
"Analytics Dashboard",
|
||||
],
|
||||
preferenceMatches: ["ecommerce", "branding"],
|
||||
},
|
||||
{
|
||||
id: "seo",
|
||||
title: "SEO & Marketing",
|
||||
description:
|
||||
"Data-driven digital marketing strategies to improve visibility and drive conversions.",
|
||||
icon: <LineChartOutlined />,
|
||||
iconClass: styles.iconSEO,
|
||||
features: [
|
||||
"Keyword Research",
|
||||
"Content Strategy",
|
||||
"Technical SEO",
|
||||
"Performance Tracking",
|
||||
],
|
||||
preferenceMatches: ["seo", "branding"],
|
||||
},
|
||||
{
|
||||
id: "mobile",
|
||||
title: "Mobile Development",
|
||||
description:
|
||||
"Native and cross-platform mobile applications for iOS and Android.",
|
||||
icon: <MobileOutlined />,
|
||||
iconClass: styles.iconMobile,
|
||||
features: [
|
||||
"iOS Development",
|
||||
"Android Development",
|
||||
"Cross-platform",
|
||||
"App Store Optimization",
|
||||
],
|
||||
preferenceMatches: ["mobile", "ai"],
|
||||
},
|
||||
{
|
||||
id: "cloud",
|
||||
title: "Cloud Solutions",
|
||||
description:
|
||||
"Scalable cloud infrastructures, migrations, and DevOps automation.",
|
||||
icon: <CloudOutlined />,
|
||||
iconClass: styles.iconCloud,
|
||||
features: [
|
||||
"AWS/Azure/GCP",
|
||||
"Infrastructure Setup",
|
||||
"DevOps Automation",
|
||||
"Scalability",
|
||||
],
|
||||
preferenceMatches: ["cloud", "ai"],
|
||||
},
|
||||
{
|
||||
id: "ai",
|
||||
title: "AI & Machine Learning",
|
||||
description:
|
||||
"Custom AI solutions for automation, prediction, and data analysis.",
|
||||
icon: <RobotOutlined />,
|
||||
iconClass: styles.iconAI,
|
||||
features: [
|
||||
"Custom AI Models",
|
||||
"Data Analysis",
|
||||
"Process Automation",
|
||||
"Predictive Analytics",
|
||||
],
|
||||
preferenceMatches: ["ai", "cloud"],
|
||||
},
|
||||
{
|
||||
id: "consulting",
|
||||
title: "Global IT Consulting",
|
||||
description:
|
||||
"Strategic technology consulting to drive digital transformation and innovation.",
|
||||
icon: <GlobalOutlined />,
|
||||
iconClass: styles.iconConsulting,
|
||||
features: [
|
||||
"Technology Strategy",
|
||||
"Digital Transformation",
|
||||
"Project Management",
|
||||
"Team Training",
|
||||
],
|
||||
preferenceMatches: ["cloud", "branding", "seo"],
|
||||
},
|
||||
];
|
||||
|
||||
const processSteps = [
|
||||
{
|
||||
number: "01",
|
||||
title: "Discovery & Planning",
|
||||
description:
|
||||
"We analyze your requirements and create a comprehensive project plan tailored to your goals.",
|
||||
},
|
||||
{
|
||||
number: "02",
|
||||
title: "Design & Development",
|
||||
description:
|
||||
"Our expert team builds your solution using the latest technologies and best practices.",
|
||||
},
|
||||
{
|
||||
number: "03",
|
||||
title: "Testing & Quality",
|
||||
description:
|
||||
"Rigorous testing ensures your solution is robust, secure, and performs flawlessly.",
|
||||
},
|
||||
{
|
||||
number: "04",
|
||||
title: "Launch & Support",
|
||||
description:
|
||||
"We deploy your solution and provide ongoing support to ensure continued success.",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ServicesPage() {
|
||||
const services = allServices;
|
||||
|
||||
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 (
|
||||
<main className={styles.main}>
|
||||
{/* Hero Section */}
|
||||
<section className={styles.heroSection}>
|
||||
<div className={styles.heroBackground}>
|
||||
<div className={styles.heroOrb1}></div>
|
||||
<div className={styles.heroOrb2}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.heroContent}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<Title level={1} className={styles.heroTitle}>
|
||||
Our <span className={styles.gradientText}>Services</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.heroSubtitle}>
|
||||
Innovative technology solutions customized for your business
|
||||
needs. From web development to AI solutions, we deliver excellence
|
||||
in every project.
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.serviceStats}>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>50+</span>
|
||||
<span className={styles.statLabel}>Projects Completed</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>8</span>
|
||||
<span className={styles.statLabel}>Service Categories</span>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>100%</span>
|
||||
<span className={styles.statLabel}>Client Satisfaction</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section className={styles.servicesSection}>
|
||||
<div className={styles.servicesBackground}></div>
|
||||
<div className={styles.servicesContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.servicesHeader}
|
||||
>
|
||||
<Title level={2} className={styles.servicesTitle}>
|
||||
What We <span className={styles.gradientText}>Offer</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.servicesSubtitle}>
|
||||
Comprehensive technology solutions designed to drive your business
|
||||
forward. Each service is crafted with precision and delivered with
|
||||
excellence.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.servicesGrid}
|
||||
>
|
||||
{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>
|
||||
|
||||
<Paragraph className={styles.serviceDescription}>
|
||||
{service.description}
|
||||
</Paragraph>
|
||||
|
||||
<div className={styles.featuresContainer}>
|
||||
<h4 className={styles.featuresTitle}>Key Features</h4>
|
||||
<ul className={styles.serviceFeatures}>
|
||||
{service.features.map((feature, index) => (
|
||||
<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}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className={styles.cardFooter}>
|
||||
<Button type="primary" className={styles.learnMoreBtn}>
|
||||
Explore Service <ArrowRightOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Process Section */}
|
||||
<section className={styles.processSection}>
|
||||
<div className={styles.processBackground}></div>
|
||||
<div className={styles.processContainer}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
viewport={{ once: true }}
|
||||
className={styles.processHeader}
|
||||
>
|
||||
<Title level={2} className={styles.processTitle}>
|
||||
Our <span className={styles.gradientText}>Process</span>
|
||||
</Title>
|
||||
<Paragraph className={styles.processSubtitle}>
|
||||
A proven methodology that ensures successful project delivery and
|
||||
exceeds expectations.
|
||||
</Paragraph>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
className={styles.processSteps}
|
||||
>
|
||||
{processSteps.map((step, index) => (
|
||||
<motion.div key={index} variants={itemVariants}>
|
||||
<div className={styles.processStep}>
|
||||
<div className={styles.stepNumber}>{step.number}</div>
|
||||
<Title level={4} className={styles.stepTitle}>
|
||||
{step.title}
|
||||
</Title>
|
||||
<Paragraph className={styles.stepDescription}>
|
||||
{step.description}
|
||||
</Paragraph>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
44
src/app/sitemap.ts
Normal file
44
src/app/sitemap.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { MetadataRoute } from 'next'
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const baseUrl = 'https://tech-masters.guru'
|
||||
|
||||
return [
|
||||
{
|
||||
url: baseUrl,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/about`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/services`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/projects`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/testimonials`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.7,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/contact`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.8,
|
||||
},
|
||||
]
|
||||
}
|
||||
32
src/app/testimonials/layout.tsx
Normal file
32
src/app/testimonials/layout.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Client Testimonials | Tech Master - What Our Clients Say",
|
||||
description: "Read testimonials from our satisfied clients in Dubai. Discover how Tech Master has helped businesses achieve digital transformation and success through innovative IT solutions.",
|
||||
keywords: [
|
||||
"client testimonials",
|
||||
"customer reviews",
|
||||
"Dubai IT company reviews",
|
||||
"digital transformation success",
|
||||
"IT solutions testimonials",
|
||||
"web development reviews",
|
||||
"mobile app development feedback",
|
||||
"enterprise software testimonials"
|
||||
],
|
||||
openGraph: {
|
||||
title: "Client Testimonials | Tech Master - What Our Clients Say",
|
||||
description: "Read testimonials from our satisfied clients in Dubai. Discover how Tech Master has helped businesses achieve digital transformation.",
|
||||
url: "https://tech-masters.guru/testimonials",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "/testimonials",
|
||||
},
|
||||
};
|
||||
|
||||
export default function TestimonialsLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
11
src/app/testimonials/page.tsx
Normal file
11
src/app/testimonials/page.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import TestimonialsSection from "../components/Testimonials/Testimonials";
|
||||
|
||||
export default function TestimonialsPage() {
|
||||
return (
|
||||
<main className="pt-20">
|
||||
<TestimonialsSection />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
@@ -11,7 +15,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
@@ -19,9 +23,19 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user