Files
Wdipl-react/components/ProcessSection.tsx
2026-04-17 14:52:57 +05:30

321 lines
10 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { motion } from "framer-motion";
import { useRef } from "react";
import {
ArrowRight,
FileText,
Users,
CheckCircle,
Rocket,
Search,
Code,
Palette,
Monitor,
} from "lucide-react";
import { Button } from "./ui/button";
import { Badge } from "./ui/badge";
import { useNavigate } from "react-router-dom";
const steps = [
{
id: "step-1",
title: "1. Define Scope",
description:
"We start by gathering project data and requirements, defining the project goals, creating technical documentation, and aligning these with the clients expectations.",
visual: {
type: "icon_or_doc_mockup",
style: "minimal_ui",
},
},
{
id: "step-2",
title: "2. Design UI/UX",
description:
"Using Figma, our designers craft user-centric interfaces that feature clickable flows, visual systems, and detailed wireframes for work across all screens.",
tags: [
{ label: "Wireframes", color: "#6366F1" },
{ label: "Prototyping", color: "#10B981" },
{ label: "UI System", color: "#F59E0B" },
],
},
{
id: "step-3",
title: "3. Development with Agile Sprints",
description:
"Using Agile sprints, we turn designs into production-ready code that supports continuous integration and weekly builds.",
tags: [
{ label: "Frontend", color: "#3B82F6" },
{ label: "Backend", color: "#0EA5E9" },
{ label: "APIs", color: "#8B5CF6" },
],
},
{
id: "step-4",
title: "4. Testing, Launch, and Scale",
description:
"Once we are through with QA and UAT, we launch the app. Then we monitor, iterate, and scale the app to grow alongside your user base and demand.",
chat_simulation: [
{ from: "You", text: "Are we ready to go live?" },
{ from: "Team", text: "Yes! Final tests passed 🚀" },
],
},
];
// Chat simulation component - Compact version
const ChatSimulation = ({
messages,
}: {
messages: Array<{ from: string; text: string }>;
}) => {
return (
<div className="space-y-2 p-3 bg-background rounded-lg border border-border">
{messages.map((message, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: message.from === "You" ? -20 : 20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.5, delay: index * 0.3 }}
viewport={{ once: true }}
className={`flex ${
message.from === "You" ? "justify-start" : "justify-end"
}`}
>
<div
className={`max-w-[80%] px-3 py-1.5 rounded-lg ${
message.from === "You"
? "bg-muted border border-border text-foreground"
: "bg-accent text-accent-foreground"
}`}
>
<div className="text-xs font-medium mb-1 opacity-70">
{message.from}
</div>
<div className="text-xs">{message.text}</div>
</div>
</motion.div>
))}
</div>
);
};
// Document mockup component - Compact version
const DocumentMockup = () => {
return (
<div className="relative">
<div className="w-full bg-background rounded-lg border border-border p-4">
<div className="space-y-3">
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<FileText className="w-4 h-4 text-accent" />
<span className="text-xs font-medium text-foreground">
Project Scope
</span>
</div>
<div className="text-xs text-muted-foreground">Draft v1.2</div>
</div>
{/* Document sections */}
<div className="space-y-2">
<motion.div
initial={{ opacity: 0, width: 0 }}
whileInView={{ opacity: 1, width: "100%" }}
transition={{ duration: 0.8, delay: 0.2 }}
viewport={{ once: true }}
className="space-y-1.5"
>
<div className="h-1.5 bg-muted rounded w-3/4"></div>
<div className="h-1.5 bg-muted/60 rounded w-full"></div>
<div className="h-1.5 bg-muted/60 rounded w-5/6"></div>
</motion.div>
<div className="flex gap-2">
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: 0.4 }}
viewport={{ once: true }}
className="flex items-center gap-1 px-2 py-1 bg-muted rounded text-xs"
>
<CheckCircle className="w-3 h-3 text-green-500" />
<span className="text-muted-foreground">Requirements</span>
</motion.div>
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: 0.6 }}
viewport={{ once: true }}
className="flex items-center gap-1 px-2 py-1 bg-muted rounded text-xs"
>
<Search className="w-3 h-3 text-blue-400" />
<span className="text-muted-foreground">Research</span>
</motion.div>
</div>
</div>
</div>
</div>
</div>
);
};
// Process step card component
const ProcessCard = ({
step,
index,
}: {
step: (typeof steps)[0];
index: number;
}) => {
const cardRef = useRef(null);
const renderContent = () => {
if (step.visual?.type === "icon_or_doc_mockup") {
return <DocumentMockup />;
}
if (step.chat_simulation) {
return <ChatSimulation messages={step.chat_simulation} />;
}
if (step.tags) {
return (
<div className="flex flex-wrap gap-2">
{step.tags.map((tag, tagIndex) => (
<motion.div
key={tagIndex}
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.4, delay: tagIndex * 0.1 }}
viewport={{ once: true }}
>
<Badge
className="text-white border-0 px-3 py-1 text-xs font-medium rounded-lg"
style={{ backgroundColor: tag.color }}
>
{tag.label}
</Badge>
</motion.div>
))}
</div>
);
}
return null;
};
return (
<motion.div
ref={cardRef}
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: index * 0.15 }}
viewport={{ once: true, margin: "-50px" }}
className="bg-card rounded-lg border border-border hover:border-border/80 transition-all duration-300 overflow-hidden group hover:shadow-lg"
>
<div className="p-6 space-y-4">
{/* Header */}
<div className="space-y-3">
<motion.h3
initial={{ opacity: 0, y: 10 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.15 + 0.2 }}
viewport={{ once: true }}
className="text-foreground leading-tight text-lg"
>
{step.title}
</motion.h3>
<motion.p
initial={{ opacity: 0, y: 10 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.15 + 0.3 }}
viewport={{ once: true }}
className="text-muted-foreground leading-relaxed text-base"
>
{step.description}
</motion.p>
</div>
{/* Content */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.15 + 0.4 }}
viewport={{ once: true }}
>
{renderContent()}
</motion.div>
</div>
</motion.div>
);
};
interface ProcessSectionProps {
country?: string;
}
export const ProcessSection = ({ country = "USA" }: ProcessSectionProps) => {
const titleRef = useRef(null);
const navigate = useNavigate();
return (
<section className="relative overflow-hidden py-20 bg-background">
<div className="container mx-auto px-6 lg:px-8">
{/* Title Section */}
<div ref={titleRef} className="text-center mb-16">
<motion.h2
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className="text-4xl lg:text-5xl font-semibold text-foreground mb-4"
>
From Ideation to Implementation:{" "}
<span className="text-accent">
How We Convert Ideas Into Market-Ready Products
</span>
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
viewport={{ once: true }}
className="text-muted-foreground text-xl max-w-2xl mx-auto"
>
As a mobile app development company in the {country}, we turn the
vision you have for your app into reality through expert planning,
innovative design, and intuitive engineering.
</motion.p>
</div>
{/* Cards Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 max-w-6xl mx-auto">
{steps.map((step, index) => (
<ProcessCard key={step.id} step={step} index={index} />
))}
</div>
{/* Bottom CTA */}
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.8 }}
viewport={{ once: true }}
className="text-center mt-16"
>
<Button
size="lg"
className="bg-accent hover:bg-accent/90 text-accent-foreground border-0 rounded-lg px-8 py-4 group text-lg"
onClick={() => navigate("/start-a-project")}
>
<span className="flex items-center gap-2">
Start Your Project Today
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</span>
</Button>
</motion.div>
</div>
</section>
);
};