mirror of
https://github.com/OwethuManagedServices/oms-website-nextjs.git
synced 2025-12-17 18:58:10 +00:00
Home page completed
This commit is contained in:
43
app/(website)/_components/CallToActionSection.tsx
Normal file
43
app/(website)/_components/CallToActionSection.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
// components/CallToActionSection.tsx
|
||||
import React from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
|
||||
type CallToActionSectionProps = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
buttonText: string;
|
||||
buttonHref: string;
|
||||
};
|
||||
|
||||
const CallToActionSection: React.FC<CallToActionSectionProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
buttonText,
|
||||
buttonHref,
|
||||
}) => {
|
||||
return (
|
||||
// Use primary background, primary-foreground for text
|
||||
<section className="bg-primary text-primary-foreground py-16 md:py-20">
|
||||
{" "}
|
||||
{/* Adjusted padding */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
{" "}
|
||||
{/* Use container */}
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">{title}</h2>{" "}
|
||||
{/* Text color inherited */}
|
||||
<p className="text-lg mb-8 max-w-xl mx-auto opacity-90">
|
||||
{subtitle}
|
||||
</p>{" "}
|
||||
{/* Slightly less emphasis */}
|
||||
{/* Button needs contrast on primary bg. Use a secondary/outline/custom variant */}
|
||||
<Button href={buttonHref} variant="secondary" size="lg">
|
||||
{/* Example: Using 'secondary' which uses light/dark gray bg defined in globals */}
|
||||
{/* OR custom class: className="bg-background text-foreground hover:bg-background/90" */}
|
||||
{buttonText}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default CallToActionSection;
|
||||
84
app/(website)/_components/ClientLogosSection.tsx
Normal file
84
app/(website)/_components/ClientLogosSection.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
// components/ClientLogosSection.tsx
|
||||
import React from "react";
|
||||
import Image from "next/image"; // For actual logos
|
||||
import { FaBuilding, FaCar, FaLaptopCode, FaUsers } from "react-icons/fa"; // For placeholders
|
||||
|
||||
// Define structure for client data (adapt as needed)
|
||||
type Client = {
|
||||
name: string;
|
||||
logoUrl?: string; // URL to actual logo image
|
||||
icon?: React.ElementType; // Placeholder icon component
|
||||
};
|
||||
|
||||
type ClientLogosSectionProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
clients: Client[];
|
||||
};
|
||||
|
||||
const ClientLogosSection: React.FC<ClientLogosSectionProps> = ({
|
||||
title,
|
||||
description,
|
||||
clients,
|
||||
}) => {
|
||||
return (
|
||||
// Use semantic background
|
||||
<section className="py-16 md:py-20 bg-background">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
{" "}
|
||||
{/* Use container */}
|
||||
{/* Use semantic foreground */}
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-12 text-foreground">
|
||||
{title}
|
||||
</h2>
|
||||
{/* TODO: Implement Auto-Sliding Panel (e.g., using Swiper.js or Embla Carousel) */}
|
||||
<div className="flex flex-wrap justify-center items-center gap-10 md:gap-16 opacity-70 dark:opacity-60">
|
||||
{" "}
|
||||
{/* Adjust opacity */}
|
||||
{clients.map((client, index) => (
|
||||
<div
|
||||
key={index}
|
||||
title={client.name}
|
||||
className="transition-opacity hover:opacity-100"
|
||||
>
|
||||
{client.logoUrl ? (
|
||||
<Image
|
||||
src={client.logoUrl}
|
||||
alt={`${client.name} Logo`}
|
||||
width={120} // Adjust size as needed
|
||||
height={40} // Adjust size as needed
|
||||
objectFit="contain"
|
||||
className="dark:invert dark:filter" // Example: Invert logo colors in dark mode if needed
|
||||
/>
|
||||
) : client.icon ? (
|
||||
// Use semantic muted foreground for icons, primary on hover
|
||||
React.createElement(client.icon, {
|
||||
className:
|
||||
"text-5xl text-muted-foreground/80 hover:text-primary transition-colors",
|
||||
})
|
||||
) : (
|
||||
<span className="text-muted-foreground">{client.name}</span> // Fallback text
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{description && (
|
||||
<p className="mt-8 text-muted-foreground italic text-sm">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example default data matching the original page (using placeholders)
|
||||
export const defaultClients: Client[] = [
|
||||
{ name: "Financial Services Client", icon: FaBuilding },
|
||||
{ name: "Automotive Client", icon: FaCar },
|
||||
{ name: "Tech Industry Client", icon: FaLaptopCode },
|
||||
{ name: "Generic Client 1", icon: FaUsers },
|
||||
{ name: "Generic Client 2", icon: FaBuilding },
|
||||
];
|
||||
|
||||
export default ClientLogosSection;
|
||||
76
app/(website)/_components/CoreServicesSection.tsx
Normal file
76
app/(website)/_components/CoreServicesSection.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
// components/CoreServicesSection.tsx
|
||||
import React from "react";
|
||||
import ServiceCard from "./ServiceCard";
|
||||
import { FaCogs, FaProjectDiagram, FaCode } from "react-icons/fa"; // Example icons
|
||||
|
||||
// Define the structure for a service item
|
||||
type ServiceItem = {
|
||||
icon: React.ElementType;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
// Define props for the section
|
||||
type CoreServicesSectionProps = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
services: ServiceItem[];
|
||||
};
|
||||
|
||||
const CoreServicesSection: React.FC<CoreServicesSectionProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
services,
|
||||
}) => {
|
||||
return (
|
||||
// Use semantic secondary background
|
||||
<section className="py-20 md:py-28 bg-secondary">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
{" "}
|
||||
{/* Use container */}
|
||||
{/* Use semantic foreground */}
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-foreground">
|
||||
{title}
|
||||
</h2>
|
||||
{/* Use semantic muted foreground */}
|
||||
<p className="text-lg text-muted-foreground mb-12 md:mb-16 max-w-2xl mx-auto">
|
||||
{subtitle}
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 md:gap-12">
|
||||
{services.map((service, index) => (
|
||||
<ServiceCard
|
||||
key={index}
|
||||
icon={service.icon}
|
||||
title={service.title}
|
||||
description={service.description}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example default data matching the original page
|
||||
export const defaultCoreServices: ServiceItem[] = [
|
||||
{
|
||||
icon: FaCogs,
|
||||
title: "Resource Augmentation",
|
||||
description:
|
||||
"Access top-tier IT talent seamlessly integrated with your team. Skilled professionals for short-term projects or long-term engagements.",
|
||||
},
|
||||
{
|
||||
icon: FaProjectDiagram,
|
||||
title: "Project Management",
|
||||
description:
|
||||
"Expert management ensuring on-time, within-budget delivery with superior results, risk mitigation, and maximum efficiency.",
|
||||
},
|
||||
{
|
||||
icon: FaCode,
|
||||
title: "Product Development",
|
||||
description:
|
||||
"Creating innovative, scalable digital products from concept to deployment to enhance efficiency and foster business growth.",
|
||||
},
|
||||
];
|
||||
|
||||
export default CoreServicesSection;
|
||||
108
app/(website)/_components/FeaturedProductSection.tsx
Normal file
108
app/(website)/_components/FeaturedProductSection.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
// components/FeaturedProductSection.tsx
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Button from "@/components/ui/Button";
|
||||
import { FiCheckCircle, FiArrowRight } from "react-icons/fi"; // Example icons
|
||||
|
||||
type FeaturePoint = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
type FeaturedProductProps = {
|
||||
eyebrow?: string;
|
||||
title: string;
|
||||
productName: string; // e.g., "OBSE"
|
||||
description: string;
|
||||
features: FeaturePoint[];
|
||||
buttonText: string;
|
||||
buttonHref: string;
|
||||
imageUrl: string; // Path to product graphic/mockup
|
||||
imageAlt: string;
|
||||
};
|
||||
|
||||
const FeaturedProductSection: React.FC<FeaturedProductProps> = ({
|
||||
eyebrow,
|
||||
title,
|
||||
productName,
|
||||
description,
|
||||
features,
|
||||
buttonText,
|
||||
buttonHref,
|
||||
imageUrl,
|
||||
imageAlt,
|
||||
}) => {
|
||||
return (
|
||||
// Use secondary background for visual separation
|
||||
<section className="py-20 md:py-28 bg-secondary overflow-hidden">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col md:flex-row items-center gap-12 md:gap-16 lg:gap-20">
|
||||
{/* Text Content Area (Takes up half on desktop) */}
|
||||
<div className="md:w-1/2 text-center md:text-left">
|
||||
{eyebrow && (
|
||||
<p className="text-sm font-semibold uppercase tracking-wider text-primary mb-3">
|
||||
{eyebrow}
|
||||
</p>
|
||||
)}
|
||||
{/* Main title uses foreground color */}
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4 text-foreground">
|
||||
{title} <span className="text-primary">{productName}</span>
|
||||
</h2>
|
||||
{/* Description uses muted foreground */}
|
||||
<p className="text-lg text-muted-foreground mb-6">{description}</p>
|
||||
{/* Feature List */}
|
||||
<ul className="space-y-3 mb-8 text-left">
|
||||
{" "}
|
||||
{/* Ensure list is left-aligned */}
|
||||
{features.map((feature, index) => (
|
||||
<li key={index} className="flex items-start">
|
||||
<FiCheckCircle className="w-5 h-5 text-primary mr-3 mt-1 flex-shrink-0" />
|
||||
{/* Feature text uses muted foreground */}
|
||||
<span className="text-muted-foreground">{feature.text}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Call to Action Button */}
|
||||
<Button
|
||||
href={buttonHref}
|
||||
variant="primary"
|
||||
size="lg"
|
||||
className="group"
|
||||
>
|
||||
{buttonText}
|
||||
<FiArrowRight className="ml-2 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Image Area (Takes up half on desktop) */}
|
||||
<div className="md:w-1/2 relative flex justify-center">
|
||||
{/* Add perspective/shadow for visual lift */}
|
||||
<div className="relative w-full max-w-md lg:max-w-lg xl:max-w-xl rounded-lg shadow-2xl overflow-hidden transform transition-transform duration-500 hover:scale-105">
|
||||
{/* Apply subtle dark overlay on image if needed for contrast */}
|
||||
{/* <div className="absolute inset-0 bg-gradient-to-t from-black/10 to-transparent dark:from-black/20 z-10"></div> */}
|
||||
<Image
|
||||
src={imageUrl}
|
||||
alt={imageAlt}
|
||||
width={600} // Adjust intrinsic size
|
||||
height={450} // Adjust intrinsic size
|
||||
layout="responsive" // Makes image scale
|
||||
objectFit="cover" // Or 'contain' depending on image
|
||||
className="relative z-0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example default data for OBSE
|
||||
export const defaultObseFeatures: FeaturePoint[] = [
|
||||
{ text: "Automate data extraction & analysis from bank statements." },
|
||||
{ text: "Reduce manual errors and increase processing speed." },
|
||||
{ text: "Gain deep insights into financial health and trends." },
|
||||
{ text: "Enhance fraud detection capabilities." },
|
||||
{ text: "Seamless integration with existing financial systems." },
|
||||
];
|
||||
|
||||
export default FeaturedProductSection;
|
||||
67
app/(website)/_components/HeroSection.tsx
Normal file
67
app/(website)/_components/HeroSection.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
// components/HeroSection.tsx
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Button from "@/components/ui/Button"; // Use the updated Button
|
||||
|
||||
type HeroSectionProps = {
|
||||
title: React.ReactNode; // Allow JSX like <br/>
|
||||
subtitle: string;
|
||||
buttonText: string;
|
||||
buttonHref: string;
|
||||
imageUrl?: string; // Optional image URL
|
||||
// videoUrl?: string; // Optional video URL
|
||||
};
|
||||
|
||||
const HeroSection: React.FC<HeroSectionProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
buttonText,
|
||||
buttonHref,
|
||||
imageUrl = "/hero-bg.jpg", // Default background image
|
||||
}) => {
|
||||
return (
|
||||
<section className="relative h-[70vh] md:h-[85vh] flex items-center justify-center text-center bg-gradient-to-b from-black/10 to-black/40 text-white overflow-hidden">
|
||||
{" "}
|
||||
{/* Adjusted background */}
|
||||
{/* Background Image/Video */}
|
||||
<div className="absolute inset-0 z-0 opacity-40 dark:opacity-30">
|
||||
{" "}
|
||||
{/* Adjusted opacity */}
|
||||
{imageUrl && (
|
||||
<Image
|
||||
src={imageUrl}
|
||||
alt="Hero background"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
quality={75}
|
||||
priority // Load hero image quickly
|
||||
/>
|
||||
)}
|
||||
{/* TODO: Add video support if needed */}
|
||||
</div>
|
||||
{/* Overlay for better text contrast */}
|
||||
<div className="absolute inset-0 bg-black/60 z-10"></div>
|
||||
{/* Content */}
|
||||
<div className="relative z-20 container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{" "}
|
||||
{/* Use container */}
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold mb-4 leading-tight text-primary animate-fade-in-up">
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-lg md:text-xl max-w-3xl mx-auto mb-8 text-gray-200 dark:text-gray-300 animate-fade-in-up animation-delay-300">
|
||||
{subtitle}
|
||||
</p>
|
||||
<Button
|
||||
href={buttonHref}
|
||||
variant="primary" // Use primary variant defined in Button component
|
||||
size="lg"
|
||||
className="animate-fade-in-up animation-delay-600"
|
||||
>
|
||||
{buttonText} → {/* Simple arrow */}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSection;
|
||||
98
app/(website)/_components/HeroSectionDynamic.tsx
Normal file
98
app/(website)/_components/HeroSectionDynamic.tsx
Normal file
@ -0,0 +1,98 @@
|
||||
// components/HeroSectionDynamic.tsx
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Button from "@/components/ui/Button"; // Use the updated Button
|
||||
import { FiArrowRight } from "react-icons/fi";
|
||||
|
||||
type HeroSectionProps = {
|
||||
title: React.ReactNode; // Allow JSX like <br/>
|
||||
subtitle: string;
|
||||
buttonText: string;
|
||||
buttonHref: string;
|
||||
imageUrl?: string; // Main background visual
|
||||
};
|
||||
|
||||
const HeroSectionDynamic: React.FC<HeroSectionProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
buttonText,
|
||||
buttonHref,
|
||||
imageUrl = "/hero-bg.jpg", // Ensure this high-quality image exists
|
||||
}) => {
|
||||
return (
|
||||
<section className="relative flex items-center bg-background min-h-screen overflow-hidden">
|
||||
{/* Layer 1: Background Image/Gradient */}
|
||||
<div className="absolute inset-0 z-0">
|
||||
{imageUrl && (
|
||||
<Image
|
||||
src={imageUrl}
|
||||
alt="Innovative Technology Background"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
quality={85}
|
||||
priority
|
||||
className="opacity-40 dark:opacity-30" // Slightly dim the image
|
||||
/>
|
||||
)}
|
||||
{/* Fallback gradient if no image */}
|
||||
{/* <div className="absolute inset-0 bg-gradient-to-br from-secondary via-background to-background"></div> */}
|
||||
{/* Subtle Vignette Effect */}
|
||||
<div className="absolute inset-0 z-10 bg-gradient-radial from-transparent via-transparent to-background/60 dark:to-background/80"></div>
|
||||
</div>
|
||||
|
||||
{/* Layer 2: Floating Abstract Shapes (Subtle animation) */}
|
||||
{/* Shape 1 - Soft Primary Color Blob */}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute top-[10%] left-[5%] w-48 h-48 md:w-72 md:h-72 bg-primary/10 dark:bg-primary/15 rounded-full filter blur-3xl opacity-70 dark:opacity-50 animate-float animation-delay-300 z-10"
|
||||
></div>
|
||||
{/* Shape 2 - Outline Shape */}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute bottom-[15%] right-[8%] w-40 h-40 md:w-56 md:h-56 border-2 border-primary/30 dark:border-primary/40 rounded-lg opacity-50 animate-drift z-10 transform rotate-12 hidden lg:block"
|
||||
></div>
|
||||
{/* Shape 3 - Small Accent */}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute top-[25%] right-[15%] w-12 h-12 bg-secondary dark:bg-secondary/50 rounded-full opacity-60 animate-pulse-slow z-10 hidden md:block"
|
||||
></div>
|
||||
|
||||
{/* Layer 3: Content */}
|
||||
<div className="relative z-20 container mx-auto px-4 sm:px-6 lg:px-8 py-24 md:py-32">
|
||||
<div className="max-w-2xl lg:max-w-3xl text-center md:text-left">
|
||||
{" "}
|
||||
{/* Max width for content */}
|
||||
{/* Optional: Small "Eyebrow" text */}
|
||||
<p className="text-sm font-semibold uppercase tracking-wider text-primary mb-3 animate-fade-in-up">
|
||||
Owethu Managed Services
|
||||
</p>
|
||||
{/* Title - Larger, bolder */}
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold mb-6 leading-tight text-foreground animate-fade-in-up animation-delay-300">
|
||||
{/* Example gradient text - remove class if not desired */}
|
||||
<span className="bg-gradient-to-r from-primary via-primary/80 to-foreground/80 dark:to-foreground/90 bg-clip-text text-transparent">
|
||||
{title}
|
||||
</span>
|
||||
</h1>
|
||||
{/* Subtitle - Clear foreground color */}
|
||||
<p className="text-lg md:text-xl lg:text-2xl max-w-xl text-foreground/80 dark:text-foreground/70 mb-10 animate-fade-in-up animation-delay-600">
|
||||
{subtitle}
|
||||
</p>
|
||||
{/* Button - Primary variant */}
|
||||
<div className="animate-fade-in-up animation-delay-900">
|
||||
<Button
|
||||
href={buttonHref}
|
||||
variant="primary"
|
||||
size="lg"
|
||||
className="group shadow-lg hover:shadow-primary/30 dark:hover:shadow-primary/20 transform transition-all duration-300 hover:scale-105" // Enhanced hover
|
||||
>
|
||||
{buttonText}
|
||||
<FiArrowRight className="ml-2 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSectionDynamic;
|
||||
80
app/(website)/_components/HeroSectionModern.tsx
Normal file
80
app/(website)/_components/HeroSectionModern.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
// components/HeroSectionModern.tsx
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Button from "@/components/ui/Button"; // Use the updated Button
|
||||
|
||||
type HeroSectionProps = {
|
||||
title: React.ReactNode; // Allow JSX like <br/>
|
||||
subtitle: string;
|
||||
buttonText: string;
|
||||
buttonHref: string;
|
||||
imageUrl?: string; // Optional image URL
|
||||
// videoUrl?: string; // Optional video URL
|
||||
};
|
||||
|
||||
const HeroSectionModern: React.FC<HeroSectionProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
buttonText,
|
||||
buttonHref,
|
||||
imageUrl = "/hero-bg.jpg", // Default background image - MAKE SURE THIS EXISTS
|
||||
}) => {
|
||||
return (
|
||||
// Use min-h-screen for full viewport height adjust if needed
|
||||
<section className="relative flex flex-col md:flex-row items-center bg-background min-h-[80vh] md:min-h-screen overflow-hidden">
|
||||
{/* Background Image/Video Layer */}
|
||||
<div className="absolute inset-0 z-0">
|
||||
{imageUrl && (
|
||||
<Image
|
||||
src={imageUrl}
|
||||
alt="OMS Hero background"
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
quality={80} // Slightly higher quality
|
||||
priority
|
||||
// Add subtle zoom/pan animation on load (optional)
|
||||
className="animate-[scale_1.05s_ease-out_forwards]" // Requires scale keyframes in globals.css
|
||||
/>
|
||||
)}
|
||||
{/* TODO: Add video support if needed */}
|
||||
|
||||
{/* Gradient Overlay - Stronger on left, fades towards right */}
|
||||
{/* Adjust gradient stops and colors based on light/dark mode */}
|
||||
<div className="absolute inset-0 z-10 bg-gradient-to-r from-background via-background/70 to-background/10 dark:from-background dark:via-background/80 dark:to-background/20"></div>
|
||||
</div>
|
||||
|
||||
{/* Content Area (Takes up roughly half on desktop) */}
|
||||
<div className="relative z-20 w-full md:w-1/2 lg:w-3/5 h-full flex items-center py-20 md:py-0">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 md:px-12 text-center md:text-left">
|
||||
{" "}
|
||||
{/* Container for padding */}
|
||||
{/* Title - Using Primary color */}
|
||||
<h1 className="text-4xl sm:text-5xl lg:text-6xl xl:text-7xl font-bold mb-5 md:mb-6 leading-tight text-primary animate-fade-in-up">
|
||||
{title}
|
||||
</h1>
|
||||
{/* Subtitle - Using Foreground color */}
|
||||
<p className="text-lg sm:text-xl lg:text-2xl max-w-xl mx-auto md:mx-0 mb-8 md:mb-10 text-foreground/90 dark:text-foreground/80 animate-fade-in-up animation-delay-300">
|
||||
{subtitle}
|
||||
</p>
|
||||
{/* Button */}
|
||||
<div className="animate-fade-in-up animation-delay-600">
|
||||
<Button
|
||||
href={buttonHref}
|
||||
variant="primary"
|
||||
size="lg"
|
||||
className="shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-300" // Added hover effect
|
||||
>
|
||||
{buttonText} →
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Optional: Right side visual area (mostly shows background now) */}
|
||||
{/* You could add abstract shapes or other elements here if desired */}
|
||||
{/* <div className="hidden md:block md:w-1/2 lg:w-2/5 h-full"></div> */}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSectionModern;
|
||||
27
app/(website)/_components/ServiceCard.tsx
Normal file
27
app/(website)/_components/ServiceCard.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
// components/ServiceCard.tsx
|
||||
import React from "react";
|
||||
|
||||
type ServiceCardProps = {
|
||||
icon: React.ElementType; // Expect a component like FaCogs
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const ServiceCard: React.FC<ServiceCardProps> = ({
|
||||
icon: Icon,
|
||||
title,
|
||||
description,
|
||||
}) => {
|
||||
return (
|
||||
// Use semantic variables for background, text, border
|
||||
<div className="bg-card p-8 rounded-lg border border-border shadow-md hover:shadow-xl transition-shadow duration-300 text-left">
|
||||
<Icon className="text-primary text-4xl mb-4" />
|
||||
{/* Use semantic foreground for title */}
|
||||
<h3 className="text-xl font-semibold mb-3 text-foreground">{title}</h3>
|
||||
{/* Use semantic muted foreground for description */}
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServiceCard;
|
||||
97
app/(website)/_components/WhyChooseUsSection.tsx
Normal file
97
app/(website)/_components/WhyChooseUsSection.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
// components/WhyChooseUsSection.tsx
|
||||
import React from "react";
|
||||
import { IconType } from "react-icons"; // Import IconType for typing
|
||||
import { FiZap, FiUsers, FiTarget, FiBarChart2 } from "react-icons/fi"; // Example icons
|
||||
|
||||
type FeatureItem = {
|
||||
icon: IconType;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
type WhyChooseUsProps = {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
features: FeatureItem[];
|
||||
};
|
||||
|
||||
const WhyChooseUsSection: React.FC<WhyChooseUsProps> = ({
|
||||
title,
|
||||
subtitle,
|
||||
features,
|
||||
}) => {
|
||||
return (
|
||||
// Use standard background for seamless flow or secondary for slight distinction
|
||||
<section className="py-20 md:py-28 bg-background">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto text-center mb-12 md:mb-16">
|
||||
{/* Use semantic foreground */}
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-foreground">
|
||||
{title}
|
||||
</h2>
|
||||
{subtitle && (
|
||||
// Use semantic muted foreground
|
||||
<p className="text-lg text-muted-foreground">{subtitle}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Features Grid */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 md:gap-10">
|
||||
{features.map((feature, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="text-center md:text-left flex flex-col items-center md:items-start p-6 rounded-lg transition-colors duration-300 hover:bg-secondary"
|
||||
>
|
||||
{" "}
|
||||
{/* Added padding and hover */}
|
||||
<div className="flex-shrink-0 mb-4">
|
||||
{/* Icon using primary color */}
|
||||
<feature.icon className="w-10 h-10 text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
{/* Title using foreground */}
|
||||
<h3 className="text-xl font-semibold mb-2 text-foreground">
|
||||
{feature.title}
|
||||
</h3>
|
||||
{/* Description using muted foreground */}
|
||||
<p className="text-base text-muted-foreground">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example default data (adapt based on OMS's key selling points/values)
|
||||
export const defaultWhyChooseUsFeatures: FeatureItem[] = [
|
||||
{
|
||||
icon: FiZap,
|
||||
title: "Innovation Driven",
|
||||
description:
|
||||
"We leverage cutting-edge technology to create transformative solutions that push boundaries.",
|
||||
},
|
||||
{
|
||||
icon: FiUsers,
|
||||
title: "Expert Teams",
|
||||
description:
|
||||
"Access highly skilled IT professionals tailored to your project needs, ensuring expertise and quality.",
|
||||
},
|
||||
{
|
||||
icon: FiTarget,
|
||||
title: "Client-Centric Approach",
|
||||
description:
|
||||
"Your success is our priority. We partner closely with you to deliver solutions aligned with your goals.",
|
||||
},
|
||||
{
|
||||
icon: FiBarChart2,
|
||||
title: "Measurable Results",
|
||||
description:
|
||||
"Our focus is on delivering tangible business impact, enhancing efficiency and driving growth.",
|
||||
},
|
||||
];
|
||||
|
||||
export default WhyChooseUsSection;
|
||||
94
app/(website)/page.tsx
Normal file
94
app/(website)/page.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import HeroSection from "./_components/HeroSection"; // Import the HeroSection component
|
||||
import ClientLogosSection, {
|
||||
defaultClients,
|
||||
} from "./_components/ClientLogosSection"; // Import component and data
|
||||
import CallToActionSection from "./_components/CallToActionSection";
|
||||
import CoreServicesSection, {
|
||||
defaultCoreServices,
|
||||
} from "./_components/CoreServicesSection";
|
||||
import WhyChooseUsSection, {
|
||||
defaultWhyChooseUsFeatures,
|
||||
} from "./_components/WhyChooseUsSection";
|
||||
import FeaturedProductSection, {
|
||||
defaultObseFeatures,
|
||||
} from "./_components/FeaturedProductSection";
|
||||
// import HeroSectionModern from "./_components/HeroSectionModern";
|
||||
// import HeroSectionDynamic from "./_components/HeroSectionDynamic";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
{/*
|
||||
<HeroSectionDynamic
|
||||
title={<>Where Innovation Meets Excellence</>} // Simplified title for this layout
|
||||
subtitle="We deliver cutting-edge IT solutions, empowering businesses to thrive in the ever-evolving digital landscape with unmatched industry expertise."
|
||||
buttonText="Explore Solutions" // Changed button text slightly
|
||||
buttonHref="/services" // Point to services maybe?
|
||||
imageUrl="/hero-bg.jpg" // Use a different, high-quality background image
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<HeroSectionModern
|
||||
title={
|
||||
<>
|
||||
Where Innovation <br className="hidden md:block" /> Meets
|
||||
Excellence.
|
||||
</>
|
||||
}
|
||||
subtitle="Welcome to Owethu Managed Services. We deliver cutting-edge IT solutions, empowering businesses to thrive in the ever-evolving digital landscape with unmatched industry expertise."
|
||||
buttonText="Learn More"
|
||||
buttonHref="/about"
|
||||
imageUrl="/hero-bg.jpg" // Specify your hero image
|
||||
/>
|
||||
*/}
|
||||
<HeroSection
|
||||
title={
|
||||
<>
|
||||
Where Innovation <br className="hidden md:block" /> Meets
|
||||
Excellence.
|
||||
</>
|
||||
}
|
||||
subtitle="Welcome to Owethu Managed Services. We deliver cutting-edge IT solutions, empowering businesses to thrive in the ever-evolving digital landscape with unmatched industry expertise."
|
||||
buttonText="Learn More"
|
||||
buttonHref="/about"
|
||||
imageUrl="/hero-bg.jpg" // Specify your hero image
|
||||
/>
|
||||
<CoreServicesSection
|
||||
title="Core Services"
|
||||
subtitle="Tailored solutions designed to drive growth, optimize productivity, and solve your most complex business challenges."
|
||||
services={defaultCoreServices} // Pass the data
|
||||
/>
|
||||
<WhyChooseUsSection
|
||||
title="Why Partner with OMS?"
|
||||
subtitle="Combining expertise with a commitment to excellence for your success."
|
||||
features={defaultWhyChooseUsFeatures}
|
||||
/>
|
||||
<FeaturedProductSection
|
||||
eyebrow="Featured Product"
|
||||
title="Streamline Financial Analysis with"
|
||||
productName="OBSE"
|
||||
description="Our advanced Optical Bank Statement Extractor automates data aggregation, reduces errors, and provides deep financial insights."
|
||||
features={defaultObseFeatures}
|
||||
buttonText="Learn More & Demo"
|
||||
buttonHref="/products/obse" // Link to the OBSE product page
|
||||
imageUrl="/obse-mockup.png" // **IMPORTANT: Create or find a relevant image**
|
||||
imageAlt="OBSE Product Interface Mockup"
|
||||
/>
|
||||
<ClientLogosSection
|
||||
title="Trusted By Industry Leaders"
|
||||
clients={defaultClients} // Pass placeholder data
|
||||
description="Showcasing key clients across financial services, automotive, and tech industries." // Optional description
|
||||
/>
|
||||
{/* TODO: Implement actual client logo fetching and display */}
|
||||
{/* TODO: Add auto-sliding carousel for clients */}
|
||||
<CallToActionSection
|
||||
title="Ready to Innovate?"
|
||||
subtitle="Let's discuss how OMS can help transform your business with cutting-edge technology solutions."
|
||||
buttonText="Get In Touch"
|
||||
buttonHref="/contact"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user