feature: sign up with github and about page completed

This commit is contained in:
libertyoms
2025-04-21 15:44:18 +02:00
parent 5eb60015cc
commit 629da1b7e7
12 changed files with 970 additions and 297 deletions

18
actions/auth-action.ts Normal file
View File

@ -0,0 +1,18 @@
// app/actions.ts (or lib/actions.ts)
"use server"; // <--- IMPORTANT: This file contains Server Actions
import { signIn as nextAuthSignIn, signOut as nextAuthSignOut } from "@/auth";
// Define your server action to handle sign-in
export async function handleSignInAction(provider: string = "github") {
// You can add any pre-sign-in logic here if needed
await nextAuthSignIn(provider);
// You can add any post-sign-in logic or revalidates here
}
// Define your server action to handle sign-out
export async function handleSignOutAction() {
// You can add any pre-sign-out logic here if needed
await nextAuthSignOut();
// You can add any post-sign-out logic or revalidates here
}

View File

@ -0,0 +1,541 @@
import Image from "next/image";
import {
FaHandshake,
FaBullseye,
FaUsers,
FaCheckCircle,
FaHeart,
FaComments,
FaShieldAlt,
FaCogs,
FaChartLine,
FaMicrochip,
FaBriefcase,
FaSyncAlt,
FaUserCheck,
FaProjectDiagram,
} from "react-icons/fa";
const leadershipTeam = [
{
id: 1,
name: "Michael Shapiro",
title: "Managing Director",
imageUrl: "/images/profile1.jpg",
bio: "A seasoned leader and innovator with over 25 years of experience, driving strategic growth and fostering a culture of excellence within OMS.",
linkedinUrl: "#",
},
{
id: 2,
name: "Gareth Corbishley",
title: "Director",
imageUrl: "/images/profile2.jpg",
bio: "Expert in operational efficiency and technological implementation, ensuring seamless project delivery and client satisfaction.",
linkedinUrl: "#",
},
{
id: 3,
name: "Darryl Govender",
title: "Director",
imageUrl: "/images/profile3.jpg",
bio: "Specializes in aligning cutting-edge technology solutions with complex business needs to unlock transformative results.",
linkedinUrl: "#",
},
];
const coreValues = [
{
icon: FaCheckCircle,
title: "Service",
description:
"Dedicated to providing outstanding service at every touchpoint, meeting the highest standards, and creating lasting impact for our clients.",
},
{
icon: FaHandshake,
title: "Accountability",
description:
"Taking ownership of our actions and delivering on promises with transparency. Our commitment fosters trust and ensures we consistently meet client expectations.",
},
{
icon: FaHeart,
title: "Passion",
description:
"Driven by a passion for innovation, we embrace new ideas and technologies, constantly seeking ways to improve and deliver creative, boundary-pushing solutions.",
},
{
icon: FaComments,
title: "Communication",
description:
"Clear, consistent, and proactive communication is central. We ensure all stakeholders are aligned, informed, and empowered, fostering collaboration.",
},
{
icon: FaShieldAlt,
title: "Trust",
description:
"Cultivating trust through ethical practices, honesty, and transparency. We uphold the highest integrity for long-term, mutually beneficial relationships.",
},
];
const ourApproach = [
{
icon: FaProjectDiagram,
title: "Strategic Alignment",
description:
" We begin by deeply understanding your business objectives, challenges, and long-term vision to ensure every solution delivers strategic value.",
},
{
icon: FaUserCheck,
title: "Client-Centric Collaboration",
description:
"We believe in true partnership. You're involved throughout the process, ensuring transparency, feedback loops, and solutions tailored precisely to your needs.",
},
{
icon: FaSyncAlt,
title: "Agile & Adaptive Delivery",
description:
"Leveraging agile methodologies allows us to be flexible, adapt to changing requirements, and deliver incremental value faster, ensuring projects stay on track and relevant.",
},
{
icon: FaCogs,
title: "Technical Excellence",
description:
"Our commitment to technical excellence means employing best practices, rigorous testing, and seasoned expertise to build robust, scalable, and maintainable solutions.",
},
];
const industryExpertise = [
{
icon: FaBriefcase,
industry: "Financial Services & Fintech",
details:
"Deep understanding of regulatory landscapes, security requirements, and digital transformation needs within banking, insurance, and investment sectors. We build secure, compliant, and innovative fintech solutions.",
},
{
icon: FaBriefcase,
industry: "Automotive",
details:
"Experience in optimizing supply chains, developing connected car solutions, enhancing customer experiences, and leveraging data analytics for the automotive industry.",
},
{
icon: FaBriefcase,
industry: "Technology",
details:
"Partnering with tech companies to accelerate product development, provide specialized engineering talent, and build scalable cloud-native applications.",
},
{
icon: FaBriefcase,
industry: "Retail/E-commerce",
details: "Describe experience in this sector.",
},
];
export default function AboutUsPage() {
return (
<div className="bg-white text-gray-800 overflow-x-hidden">
{" "}
{/* Prevent horizontal scroll */}
{/* Section 1: Hero / Company Overview */}
<section className="relative bg-gradient-to-r from-gray-800 via-gray-700 to-gray-800 text-white py-24 md:py-40">
{/* Optional decorative background elements */}
<div className="absolute inset-0 bg-black opacity-30"></div>
<div
className="absolute inset-0 bg-cover bg-center opacity-10"
style={{ backgroundImage: "url('/path/to/abstract-tech-bg.jpg')" }}
></div>{" "}
{/* Add a subtle background image */}
<div className="container mx-auto px-6 text-center relative z-10">
<h1
className="text-4xl md:text-6xl font-bold mb-4 font-poppins text-gold-500 drop-shadow-md"
style={{ color: "#e1c44a" }}
>
About Owethu Managed Services
</h1>
<p className="text-lg md:text-xl max-w-3xl mx-auto leading-relaxed text-gray-200 font-poppins">
Your strategic partner in navigating the digital frontier. We fuse
deep technical expertise with a passion for innovation to craft
bespoke IT solutions that drive tangible business results and unlock
future potential.
</p>
</div>
</section>
{/* Section 2: Our Genesis & Purpose */}
<section className="py-16 md:py-24 bg-gray-50">
<div className="container mx-auto px-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div>
<h2 className="text-3xl md:text-4xl font-bold mb-6 font-poppins text-gray-900 leading-tight">
Forged in Innovation, <br className="hidden md:inline" /> Driven
by Purpose
</h2>
<p className="text-md md:text-lg text-gray-700 leading-relaxed mb-4 font-poppins">
Expand on the founding story/motivation. E.g., Owethu Managed
Services was born from a clear vision: to harness the
transformative power of technology not just to solve problems,
but to proactively create opportunities for businesses to
thrive. We saw a need for a partner who truly understands both
technology&apos;s potential and the unique challenges modern
organizations face.
</p>
<p className="text-md md:text-lg text-gray-700 leading-relaxed font-poppins">
Elaborate on the journey. E.g., Our journey has been defined by
a relentless pursuit of knowledge, adaptation to the
ever-evolving tech landscape, and an unwavering commitment to
client success. This focus has established us as trusted
advisors and thought leaders in digital transformation.
</p>
</div>
<div className="relative h-64 md:h-80 rounded-lg overflow-hidden shadow-lg">
{/* Replace with a relevant, high-quality image representing innovation or teamwork */}
<Image
src="/images/team-collaborative.png"
alt="Team collaborating on innovative solutions"
layout="fill"
objectFit="cover"
className="transition-transform duration-500 hover:scale-105"
/>
</div>
</div>
</div>
</section>
{/* Section 3: Vision & Mission (Similar layout, refined look) */}
<section className="py-16 md:py-24 bg-white">
<div className="container mx-auto px-6 text-center mb-12">
<h2 className="text-3xl md:text-4xl font-bold font-poppins text-gray-900">
Our North Star
</h2>
<p className="text-md md:text-lg text-gray-600 mt-3 max-w-2xl mx-auto font-poppins">
Guiding our strategy, actions, and partnerships.
</p>
</div>
<div className="container mx-auto px-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-12">
{/* Vision Card */}
<div
className="bg-gray-50 p-8 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 border-t-4 border-gold-500 flex flex-col items-center text-center"
style={{ borderColor: "#e1c44a" }}
>
<FaBullseye
className="text-5xl mb-5 text-gold-500"
style={{ color: "#e1c44a" }}
/>
<h3 className="text-2xl font-bold mb-4 font-poppins text-gray-900">
Our Vision
</h3>
<p className="text-gray-700 leading-relaxed font-poppins flex-grow">
&quot;To be global leaders in delivering cutting-edge IT
solutions, pushing the boundaries of what&apos;s possible, and
transforming industries for the better. We aim to empower
organisations to break through technological barriers and
achieve greater success.&quot;
</p>
</div>
{/* Mission Card */}
<div
className="bg-gray-50 p-8 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 border-t-4 border-gold-500 flex flex-col items-center text-center"
style={{ borderColor: "#e1c44a" }}
>
<FaHandshake
className="text-5xl mb-5 text-gold-500"
style={{ color: "#e1c44a" }}
/>
<h3 className="text-2xl font-bold mb-4 font-poppins text-gray-900">
Our Mission
</h3>
<p className="text-gray-700 leading-relaxed font-poppins flex-grow">
&quot;We are dedicated to creating tailored, innovative
solutions that drive business success. By combining expertise
with cutting-edge technology, we solve complex problems and
enable our clients to achieve outstanding results. We partner
closely with clients to ensure every solution aligns with their
unique needs for long-term success.&quot;
</p>
</div>
</div>
</div>
</section>
{/* Section 4: Our Approach & Methodology */}
<section className="py-16 md:py-24 bg-gradient-to-br from-gray-100 to-gray-200">
<div className="container mx-auto px-6">
<div className="text-center mb-14">
<h2 className="text-3xl md:text-4xl font-bold font-poppins text-gray-900 mb-4">
How We Deliver Excellence
</h2>
<p className="text-md md:text-lg text-gray-700 max-w-3xl mx-auto font-poppins">
Our methodology is built on collaboration, precision, and a
relentless focus on delivering impactful results. We tailor our
process to fit your specific project needs.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
{ourApproach.map((item) => (
<div
key={item.title}
className="bg-white p-6 rounded-lg shadow-md text-center transform transition duration-300 hover:-translate-y-2 hover:shadow-xl"
>
<item.icon
className="text-4xl text-gold-500 mx-auto mb-5"
style={{ color: "#e1c44a" }}
/>
<h4 className="text-xl font-semibold mb-3 font-poppins">
{item.title}
</h4>
<p className="text-gray-600 font-poppins text-sm leading-relaxed">
{item.description}
</p>
</div>
))}
</div>
</div>
</section>
{/* Section 5: Industry Expertise */}
<section className="py-16 md:py-24 bg-white">
<div className="container mx-auto px-6">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12 items-center">
<div className="lg:col-span-1">
<FaBriefcase
className="text-5xl text-gold-500 mb-4"
style={{ color: "#e1c44a" }}
/>
<h2 className="text-3xl md:text-4xl font-bold mb-4 font-poppins text-gray-900 leading-tight">
Deep Domain Knowledge
</h2>
<p className="text-md md:text-lg text-gray-700 leading-relaxed font-poppins">
We combine broad technological capabilities with specialized
expertise across key industries, understanding the unique
challenges and opportunities within each sector.
</p>
</div>
<div className="lg:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-6">
{industryExpertise.map((exp) => (
<div
key={exp.industry}
className="bg-gray-50 p-6 rounded-lg shadow-sm border-l-4 border-gold-500"
style={{ borderColor: "#e1c44a" }}
>
<h4 className="text-lg font-semibold mb-2 font-poppins">
{exp.industry}
</h4>
<p className="text-gray-600 font-poppins text-sm leading-relaxed">
{exp.details}
</p>
</div>
))}
</div>
</div>
</div>
</section>
{/* Section 6: Technology Philosophy */}
<section className="py-16 md:py-24 bg-gray-800 text-white">
<div className="container mx-auto px-6 text-center">
<FaMicrochip
className="text-5xl text-gold-500 mx-auto mb-5"
style={{ color: "#e1c44a" }}
/>
<h2 className="text-3xl md:text-4xl font-bold mb-4 font-poppins">
Smart Technology, Applied Wisely
</h2>
<p className="text-lg md:text-xl max-w-3xl mx-auto leading-relaxed text-gray-300 mb-8 font-poppins">
We don&apos;t chase trends; we select and implement technologies
strategically. Our focus is on building solutions that are:
</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-4xl mx-auto">
<div className="bg-gray-700 p-6 rounded-lg">
<h4
className="text-xl font-semibold mb-2 font-poppins text-gold-500"
style={{ color: "#e1c44a" }}
>
Scalable & Future-Proof
</h4>
<p className="text-gray-300 font-poppins text-sm">
Designed to grow with your business and adapt to future
technological advancements.
</p>
</div>
<div className="bg-gray-700 p-6 rounded-lg">
<h4
className="text-xl font-semibold mb-2 font-poppins text-gold-500"
style={{ color: "#e1c44a" }}
>
Robust & Reliable
</h4>
<p className="text-gray-300 font-poppins text-sm">
Built with quality and security at the core, ensuring dependable
performance.
</p>
</div>
<div className="bg-gray-700 p-6 rounded-lg">
<h4
className="text-xl font-semibold mb-2 font-poppins text-gold-500"
style={{ color: "#e1c44a" }}
>
Best-Fit Solutions
</h4>
<p className="text-gray-300 font-poppins text-sm">
Chosen based on your specific needs, budget, and existing
infrastructure, not just the latest hype.
</p>
</div>
</div>
</div>
</section>
{/* Section 7: Core Values (Reusing previous structure, adjusting background) */}
<section className="py-16 md:py-24 bg-gray-100">
<div className="container mx-auto px-6">
<h2 className="text-3xl md:text-4xl font-bold text-center mb-12 font-poppins text-gray-900">
Our Foundational Values
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
{coreValues.map((value) => (
<div
key={value.title}
className="bg-white p-6 rounded-lg shadow-sm text-center transition-shadow duration-300 hover:shadow-lg"
>
<value.icon
className="text-4xl text-gold-500 mx-auto mb-4"
style={{ color: "#e1c44a" }}
/>
<h4 className="text-xl font-semibold mb-2 font-poppins">
{value.title}
</h4>
<p className="text-gray-600 font-poppins text-sm leading-relaxed">
{value.description}
</p>
</div>
))}
</div>
</div>
</section>
{/* Section 8: The OMS Partnership */}
<section className="py-16 md:py-24 bg-white">
<div className="container mx-auto px-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div className="relative h-64 md:h-80 rounded-lg overflow-hidden shadow-lg order-last md:order-first">
{/* Replace with an image representing partnership or client collaboration */}
<Image
src="/images/partners.jpg"
alt="Client partnership and collaboration"
layout="fill"
objectFit="cover"
className="transition-transform duration-500 hover:scale-105"
/>
</div>
<div>
<FaUsers
className="text-5xl text-gold-500 mb-4"
style={{ color: "#e1c44a" }}
/>
<h2 className="text-3xl md:text-4xl font-bold mb-6 font-poppins text-gray-900 leading-tight">
More Than Vendors, <br className="hidden md:inline" />{" "}
We&apos;re Partners
</h2>
<p className="text-md md:text-lg text-gray-700 leading-relaxed mb-4 font-poppins">
We believe the best results come from true collaboration. We
invest time in understanding your culture, goals, and
challenges, working alongside your team as an extension of your
own capabilities.
</p>
<p className="text-md md:text-lg text-gray-700 leading-relaxed font-poppins">
This means open communication, shared goals, proactive
problem-solving, and a long-term commitment to your success,
extending far beyond project completion.
</p>
</div>
</div>
</div>
</section>
{/* Section 9: Our Leadership Team */}
<section className="py-16 md:py-24 bg-gray-50">
<div className="container mx-auto px-6">
<div className="text-center mb-14">
<h2 className="text-3xl md:text-4xl font-bold font-poppins text-gray-900 mb-4">
Meet Our Leadership
</h2>
<p className="text-md md:text-lg text-gray-700 max-w-3xl mx-auto font-poppins">
Slightly enhance the intro. E.g., Guided by experience and a
passion for innovation, our leadership team fosters a culture of
excellence and empowers our experts to deliver outstanding results
for our clients.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-10 justify-center">
{/* Added justify-center */}
{leadershipTeam.map((member) => (
<div
key={member.id}
className="bg-white rounded-lg shadow-lg overflow-hidden text-center transition-transform duration-300 hover:scale-105 max-w-sm mx-auto"
>
{/* Added max-width and mx-auto for centering if fewer than 3 items */}
<div className="relative h-60 w-full">
{/* Slightly taller image */}
<Image
src={member.imageUrl || "/images/profile1.jpg"}
alt={`Photo of ${member.name}`}
layout="fill"
objectFit="cover"
className="bg-gray-200"
/>
</div>
<div className="p-6">
<h4 className="text-xl font-semibold font-poppins mb-1">
{member.name}
</h4>
<p
className="text-gold-600 font-poppins text-sm mb-3"
style={{ color: "#c8a93d" }}
>
{member.title}
</p>
<p className="text-gray-600 font-poppins text-sm mb-4">
{member.bio}
</p>
{member.linkedinUrl && member.linkedinUrl !== "#" && (
<a
href={member.linkedinUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-medium text-blue-600 hover:text-blue-800 transition-colors duration-200 font-poppins"
aria-label={`LinkedIn profile of ${member.name}`}
>
{/* Using a simple text link for cleanliness */}
Connect on LinkedIn
</a>
)}
</div>
</div>
))}
</div>
{/* Button removed as requested */}
</div>
</section>
{/* Section 10: Commitment to Impact (Optional, but adds value) */}
<section
className="py-16 md:py-24 bg-gold-500 text-gray-900"
style={{ backgroundColor: "#e1c44a" }}
>
<div className="container mx-auto px-6 text-center">
<FaChartLine className="text-5xl mx-auto mb-5" />
<h2 className="text-3xl md:text-4xl font-bold mb-4 font-poppins">
Driving Measurable Impact
</h2>
<p className="text-lg md:text-xl max-w-3xl mx-auto leading-relaxed font-poppins">
Ultimately, our success is measured by yours. We are committed to
delivering solutions that not only meet technical requirements but
also drive efficiency, foster growth, enhance user experiences, and
provide a clear return on investment. Let&apos;s build a successful
future, together.
</p>
{/* Optional CTA to contact */}
<div className="mt-10">
<a
href="/contact"
className="inline-block bg-gray-800 text-white font-bold py-3 px-8 rounded-md hover:bg-gray-900 transition-colors duration-300 font-poppins"
>
Start the Conversation
</a>
</div>
</div>
</section>
</div>
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

24
app/icon.svg Normal file
View File

@ -0,0 +1,24 @@
<svg width="1005" height="1005" viewBox="0 0 1005 1005" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M502.085 0L1004.09 502L502.085 1004L0.0844712 502L502.085 0Z" fill="white"/>
<path d="M502.122 92.0752L912.207 502.16L502.122 912.244L92.0376 502.16L502.122 92.0752Z" fill="url(#paint0_linear_67_245)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M954.507 502.085L502 49.5779L49.493 502.085L502 954.592L954.507 502.085ZM502 0.0849609L2.81409e-05 502.085L502 1004.08L1004 502.085L502 0.0849609Z" fill="url(#paint1_linear_67_245)"/>
<path d="M343.932 579.034C324.45 579.034 309.266 574.083 298.379 564.181C287.492 554.279 281.762 539.57 281.189 520.053C281.046 515.891 280.975 509.792 280.975 501.756C280.975 493.576 281.046 487.405 281.189 483.244C281.762 464.158 287.636 449.52 298.809 439.331C309.982 429.142 325.023 424.048 343.932 424.048C362.841 424.048 377.881 429.142 389.055 439.331C400.371 449.52 406.316 464.158 406.889 483.244C407.176 491.567 407.319 497.738 407.319 501.756C407.319 505.631 407.176 511.73 406.889 520.053C406.173 539.57 400.371 554.279 389.485 564.181C378.598 574.083 363.413 579.034 343.932 579.034ZM343.932 554.279C353.529 554.279 361.193 551.409 366.923 545.669C372.653 539.785 375.733 530.888 376.163 518.977C376.449 510.366 376.592 504.554 376.592 501.541C376.592 498.24 376.449 492.428 376.163 484.105C375.733 472.194 372.653 463.368 366.923 457.628C361.193 451.744 353.529 448.803 343.932 448.803C334.478 448.803 326.885 451.744 321.156 457.628C315.426 463.368 312.346 472.194 311.916 484.105C311.773 488.267 311.701 494.078 311.701 501.541C311.701 508.86 311.773 514.672 311.916 518.977C312.346 530.888 315.354 539.785 320.941 545.669C326.671 551.409 334.334 554.279 343.932 554.279Z" fill="black" fill-opacity="0.87"/>
<path d="M440.906 576.881C439.33 576.881 438.041 576.451 437.038 575.59C436.035 574.585 435.534 573.294 435.534 571.715V431.582C435.534 430.003 436.035 428.712 437.038 427.707C438.041 426.703 439.33 426.2 440.906 426.2H457.881C460.889 426.2 463.038 427.564 464.327 430.29L505.797 507.783L547.697 430.29C549.129 427.564 551.278 426.2 554.143 426.2H570.903C572.479 426.2 573.768 426.703 574.771 427.707C575.773 428.712 576.275 430.003 576.275 431.582V571.715C576.275 573.294 575.773 574.585 574.771 575.59C573.768 576.451 572.479 576.881 570.903 576.881H552.854C551.421 576.881 550.204 576.379 549.201 575.374C548.198 574.37 547.697 573.15 547.697 571.715V478.508L517.615 535.982C515.753 539.139 513.317 540.718 510.309 540.718H501.5C498.491 540.718 496.056 539.139 494.194 535.982L464.112 478.508V571.715C464.112 573.15 463.611 574.37 462.608 575.374C461.748 576.379 460.531 576.881 458.955 576.881H440.906Z" fill="black" fill-opacity="0.87"/>
<path d="M661.911 579.034C649.162 579.034 638.203 577.096 629.036 573.222C619.868 569.347 612.92 564.253 608.193 557.938C603.466 551.624 600.959 544.808 600.673 537.489C600.673 536.197 601.102 535.121 601.962 534.26C602.821 533.399 603.896 532.968 605.185 532.968H624.308C626.027 532.968 627.317 533.327 628.176 534.045C629.179 534.619 630.11 535.623 630.969 537.058C632.402 541.938 635.697 546.027 640.854 549.328C646.01 552.629 653.03 554.279 661.911 554.279C672.081 554.279 679.745 552.629 684.902 549.328C690.059 545.884 692.637 541.148 692.637 535.121C692.637 531.103 691.277 527.802 688.555 525.219C685.976 522.636 682.037 520.412 676.737 518.546C671.58 516.681 663.845 514.385 653.531 511.658C636.628 507.64 624.237 502.33 616.358 495.729C608.623 488.984 604.755 479.441 604.755 467.099C604.755 458.776 606.975 451.386 611.416 444.928C616 438.47 622.518 433.376 630.969 429.645C639.564 425.913 649.52 424.048 660.837 424.048C672.583 424.048 682.753 426.129 691.348 430.29C699.943 434.452 706.461 439.69 710.901 446.004C715.485 452.175 717.921 458.346 718.207 464.516C718.207 465.808 717.777 466.884 716.918 467.745C716.058 468.606 714.984 469.037 713.695 469.037H693.712C690.704 469.037 688.627 467.674 687.481 464.947C686.621 460.355 683.756 456.552 678.886 453.538C674.015 450.381 667.999 448.803 660.837 448.803C652.815 448.803 646.512 450.309 641.928 453.323C637.344 456.337 635.052 460.713 635.052 466.454C635.052 470.472 636.198 473.772 638.49 476.356C640.782 478.939 644.363 481.235 649.233 483.244C654.247 485.253 661.409 487.477 670.721 489.917C683.326 492.787 693.354 496.016 700.803 499.603C708.395 503.191 713.981 507.712 717.562 513.165C721.144 518.618 722.934 525.578 722.934 534.045C722.934 543.229 720.356 551.265 715.199 558.154C710.185 564.898 703.023 570.065 693.712 573.652C684.544 577.24 673.944 579.034 661.911 579.034Z" fill="black" fill-opacity="0.87"/>
<defs>
<linearGradient id="paint0_linear_67_245" x1="233.025" y1="357.551" x2="595.992" y2="804.51" gradientUnits="userSpaceOnUse">
<stop offset="0.0767781" stop-color="#E1C44A"/>
<stop offset="0.290113" stop-color="#E1C44A" stop-opacity="0.7"/>
<stop offset="0.463052" stop-color="#E1C44A" stop-opacity="0.26"/>
<stop offset="0.675574" stop-color="#E1C44A" stop-opacity="0.71"/>
<stop offset="1" stop-color="#E1C44A"/>
</linearGradient>
<linearGradient id="paint1_linear_67_245" x1="346.014" y1="314.556" x2="718.674" y2="491.224" gradientUnits="userSpaceOnUse">
<stop stop-color="#E1C44A"/>
<stop offset="0.201382" stop-color="#E1C44A" stop-opacity="0.7"/>
<stop offset="0.463052" stop-color="#E1C44A" stop-opacity="0.09"/>
<stop offset="0.744023" stop-color="#E1C44A" stop-opacity="0.71"/>
<stop offset="1" stop-color="#E1C44A"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -1,303 +1,21 @@
// components/Header.tsx
"use client";
// components/Header.tsx (Server Component)
import React from "react";
import { auth } from "@/auth"; // Only need auth (for session) from here now
import React, { useState } from "react";
import Link from "next/link";
import Image from "next/image";
// Use usePathname only if needed for active state logic not shown here
// import { usePathname } from "next/navigation";
import {
FiChevronDown,
FiClipboard,
FiArrowRight,
FiMenu,
FiX,
} from "react-icons/fi";
import ThemeToggle from "./ThemeToggle"; // Assuming ThemeToggle component exists
import HeaderClient from "./HeaderClient";
import { handleSignInAction, handleSignOutAction } from "@/actions/auth-action";
const omsLogoUrl = "/oms-logo.svg"; // Ensure this is in your /public folder
// --- Basic Dropdown Component ---
// Using semantic variables for background, text, and borders
type DropdownMenuProps = {
trigger: React.ReactNode;
children: React.ReactNode;
menuClasses?: string;
};
const DropdownMenu = ({
trigger,
children,
menuClasses = "w-48",
}: DropdownMenuProps) => (
// Using group-focus-within for better keyboard/touch accessibility
<div className="relative group">
<button className="flex items-center space-x-1 text-sm font-medium focus:outline-none inherit-color group">
{trigger}
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180 group-focus-within:rotate-180" />
</button>
<div
className={`
absolute left-0 mt-2 ${menuClasses} origin-top-left rounded-md shadow-lg z-50
bg-card border border-border {/* USE SEMANTIC VARS */}
opacity-0 invisible group-hover:opacity-100 group-hover:visible group-focus-within:opacity-100 group-focus-within:visible transition-all duration-200
`}
>
<div className="py-1">{children}</div>
</div>
</div>
);
// Dropdown Link component using semantic variables
type DropdownLinkProps = {
href: string;
children: React.ReactNode;
onClick?: () => void; // Added onClick for mobile menu closure
};
const DropdownLink = ({ href, children, onClick }: DropdownLinkProps) => (
<Link
href={href}
onClick={onClick} // Call onClick if provided
className="block w-full text-left px-4 py-2 text-sm text-card-foreground hover:bg-secondary hover:text-primary" // USE SEMANTIC VARS
>
{children}
</Link>
);
// --- End Dropdown Component ---
const Header = () => {
// If you need pathname for active states later:
// const pathname = usePathname() || "/";
// const isActive = (path: string) => pathname === path;
// const isActive = (path: string) => false; // Simple placeholder
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleMenu = () => setIsMenuOpen((open) => !open);
// Close menu when a link is clicked
const handleMobileLinkClick = () => setIsMenuOpen(false);
const currentLogo = omsLogoUrl;
const Header = async () => {
// Fetch session data on the server
const session = await auth();
// Pass the session data and YOUR Server Actions as props
return (
// Use semantic variables for header background and border
<header className="sticky top-0 z-50 shadow-md bg-background border-b border-border">
{/* Top Row */}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<Link
href="/"
className="flex items-center space-x-2"
title="OMS Home"
>
<Image
src={currentLogo}
alt="OMS Logo"
width={40}
height={40}
priority
/>
{/* Use semantic variable for text color */}
<span className="text-xl font-bold text-foreground hidden sm:inline">
Owethu Managed Services
</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6 lg:space-x-8">
{/* Use semantic variables for text, hover uses primary */}
<Link
href="/"
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example (requires usePathname) */
/* ${isActive("/") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
Home
</Link>
<Link
href="/about"
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example */
/* ${pathname.startsWith("/about") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
About Us
</Link>
<Link
href="/contact"
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example */
/* ${isActive("/contact") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
Contact Us
</Link>
</nav>
{/* Right Utilities (Desktop) */}
<div className="hidden md:flex items-center space-x-4">
<ThemeToggle />
{/* Use semantic variables for button */}
<Link
href="/request-demo"
className="flex items-center text-sm font-medium bg-primary text-primary-foreground px-3 py-1.5 rounded-lg hover:bg-opacity-90 transition-colors" // Use rounded-lg from radius
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
Request Demo
</Link>
</div>
{/* Mobile Buttons */}
<div className="md:hidden flex items-center">
<ThemeToggle /> {/* Theme toggle appears first */}
<button
onClick={toggleMenu}
className="text-foreground/60 hover:text-primary focus:outline-none ml-3" // Use semantic muted color, hover primary
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
aria-controls="mobile-menu"
>
{isMenuOpen ? (
<FiX className="w-6 h-6" />
) : (
<FiMenu className="w-6 h-6" />
)}
</button>
</div>
</div>
</div>
{/* Secondary Row */}
<div className="bg-primary">
{" "}
{/* Keep gold background */}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Hide on mobile */}
<div className="hidden md:flex justify-between items-center h-12">
{/* Use primary-foreground for text color */}
<nav className="flex items-center space-x-6 lg:space-x-8 text-primary-foreground">
{/* Wrap dropdown triggers for consistent hover */}
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Services</span>}>
<DropdownLink href="/services/resource-augmentation">
Resource Augmentation
</DropdownLink>
<DropdownLink href="/services/project-management">
Project Management
</DropdownLink>
<DropdownLink href="/services/product-development">
Product Development
</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Products</span>}>
<DropdownLink href="/products/obse">OBSE</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Join Our Team</span>}>
<DropdownLink href="/join-us/vacancies">
Vacancies
</DropdownLink>
<DropdownLink href="/join-us/portal">
Recruitment Portal
</DropdownLink>
</DropdownMenu>
</div>
</nav>
{/* Use primary-foreground for link */}
<Link
href="/services"
className="flex items-center text-sm font-medium text-primary-foreground hover:text-opacity-80 transition-opacity group"
>
Explore Our Offerings
<FiArrowRight className="w-4 h-4 ml-1.5 transition-transform duration-200 group-hover:translate-x-1" />
</Link>
</div>
</div>
</div>
{/* Mobile Menu Panel */}
<div
id="mobile-menu"
// Use semantic variables for background and border
className={`md:hidden absolute top-full left-0 w-full shadow-lg transition-all duration-300 ease-in-out overflow-hidden bg-card border-t border-border ${
isMenuOpen
? "max-h-[calc(100vh-4rem)] py-4 overflow-y-auto"
: "max-h-0 py-0" // Animate height, allow scroll
}`}
>
{/* Use semantic variable for text color */}
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-1 text-foreground">
{" "}
{/* Reduced space-y */}
{/* Simplified mobile links, using DropdownLink component for consistency */}
<DropdownLink href="/" onClick={handleMobileLinkClick}>
Home
</DropdownLink>
<DropdownLink href="/about" onClick={handleMobileLinkClick}>
About Us
</DropdownLink>
{/* Maybe use collapsible sections here in a real app, but simple list for now */}
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Services
</span>
<DropdownLink
href="/services/resource-augmentation"
onClick={handleMobileLinkClick}
>
Resource Augmentation
</DropdownLink>
<DropdownLink
href="/services/project-management"
onClick={handleMobileLinkClick}
>
Project Management
</DropdownLink>
<DropdownLink
href="/services/product-development"
onClick={handleMobileLinkClick}
>
Product Development
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Products
</span>
<DropdownLink href="/products/obse" onClick={handleMobileLinkClick}>
OBSE
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Join Us
</span>
<DropdownLink
href="/join-us/vacancies"
onClick={handleMobileLinkClick}
>
Vacancies
</DropdownLink>
<DropdownLink href="/join-us/portal" onClick={handleMobileLinkClick}>
Recruitment Portal
</DropdownLink>
<DropdownLink href="/contact" onClick={handleMobileLinkClick}>
Contact Us
</DropdownLink>
{/* Demo button at the bottom */}
<div className="pt-4">
<Link
href="/request-demo"
onClick={handleMobileLinkClick}
// Use semantic variables for button style
className="flex w-full justify-center items-center text-sm font-medium bg-primary text-primary-foreground px-4 py-2 rounded-lg hover:bg-opacity-90 transition-colors"
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
Request Demo
</Link>
</div>
</nav>
</div>
</header>
<HeaderClient
session={session}
handleSignIn={handleSignInAction} // Pass YOUR sign-in Server Action
handleSignOut={handleSignOutAction} // Pass YOUR sign-out Server Action
/>
);
};

370
components/HeaderClient.tsx Normal file
View File

@ -0,0 +1,370 @@
// components/HeaderClient.tsx
"use client";
import React, { useState } from "react";
import Link from "next/link";
import Image from "next/image";
// Use usePathname only if needed for active state logic not shown here
// import { usePathname } from "next/navigation";
import {
FiChevronDown,
FiClipboard,
FiArrowRight,
FiMenu,
FiX,
FiLogIn, // Import the login icon
} from "react-icons/fi";
import ThemeToggle from "./ThemeToggle"; // Assuming ThemeToggle component exists
import type { Session } from "@auth/core/types"; // Import Session type for props
const omsLogoUrl = "/oms-logo.svg"; // Ensure this is in your /public folder
// --- Basic Dropdown Component ---
// (Keep the DropdownMenu and DropdownLink component definitions here as before)
type DropdownMenuProps = {
trigger: React.ReactNode;
children: React.ReactNode;
menuClasses?: string;
};
const DropdownMenu = ({
trigger,
children,
menuClasses = "w-48",
}: DropdownMenuProps) => (
// Using group-focus-within for better keyboard/touch accessibility
<div className="relative group">
<button className="flex items-center space-x-1 text-sm font-medium focus:outline-none inherit-color group">
{trigger}
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180 group-focus-within:rotate-180" />
</button>
<div
className={`
absolute left-0 mt-2 ${menuClasses} origin-top-left rounded-md shadow-lg z-50
bg-card border border-border {/* USE SEMANTIC VARS */}
opacity-0 invisible group-hover:opacity-100 group-hover:visible group-focus-within:opacity-100 group-focus-within:visible transition-all duration-200
`}
>
<div className="py-1">{children}</div>
</div>
</div>
);
type DropdownLinkProps = {
href: string;
children: React.ReactNode;
onClick?: () => void; // Added onClick for mobile menu closure
};
const DropdownLink = ({ href, children, onClick }: DropdownLinkProps) => (
<Link
href={href}
onClick={onClick} // Call onClick if provided
className="block w-full text-left px-4 py-2 text-sm text-card-foreground hover:bg-secondary hover:text-primary" // USE SEMANTIC VARS
>
{children}
</Link>
);
// --- End Dropdown Component ---
// --- Define Props for the Client Component ---
type HeaderClientProps = {
session: Session | null; // Accept session from the server component
handleSignIn: () => void; // Pass sign-in handler
handleSignOut: () => void; // Pass sign-out handler
};
// --- The Main Client Component ---
const HeaderClient = ({
session,
handleSignIn,
handleSignOut,
}: HeaderClientProps) => {
// --- Client-side state and hooks ---
const [isMenuOpen, setIsMenuOpen] = useState(false);
// const pathname = usePathname() || "/"; // Uncomment if needed
// const isActive = (path: string) => pathname === path; // Uncomment if needed
const toggleMenu = () => setIsMenuOpen((open) => !open);
const handleMobileLinkClick = () => setIsMenuOpen(false);
const currentLogo = omsLogoUrl;
return (
// Use semantic variables for header background and border
<header className="sticky top-0 z-50 shadow-md bg-background border-b border-border">
{/* Top Row */}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<Link
href="/"
className="flex items-center space-x-2"
title="OMS Home"
>
<Image
src={currentLogo}
alt="OMS Logo"
width={40}
height={40}
priority
/>
{/* Use semantic variable for text color */}
<span className="text-xl font-bold text-foreground hidden sm:inline">
Owethu Managed Services
</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6 lg:space-x-8">
{/* Use semantic variables for text, hover uses primary */}
<Link
href="/"
className={`text-sm font-medium text-foreground/80 hover:text-primary transition`}
>
Home
</Link>
<Link
href="/about"
className={`text-sm font-medium text-foreground/80 hover:text-primary transition`}
>
About Us
</Link>
<Link
href="/contact"
className={`text-sm font-medium text-foreground/80 hover:text-primary transition`}
>
Contact Us
</Link>
</nav>
{/* Desktop Utilities */}
<div className="hidden md:flex items-center space-x-4">
<ThemeToggle />
{/* Request Demo Button */}
<Link
href="/request-demo"
className="flex items-center text-sm font-medium bg-primary text-primary-foreground px-3 py-1.5 rounded-lg hover:bg-opacity-90 transition-colors"
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
Request Demo
</Link>
{/* --- Auth Section --- */}
{session?.user ? (
// Logged In: User Dropdown
<DropdownMenu
menuClasses="w-40 right-0 left-auto" // Align dropdown to the right
trigger={
<div className="flex items-center space-x-2 cursor-pointer hover:opacity-80 transition">
<Image
src={session.user.image || "/default-avatar.png"} // Provide a fallback avatar
alt={session.user.name || "User"}
width={32}
height={32}
className="rounded-full ring-1 ring-primary ring-offset-2 ring-offset-background" // Added offset
/>
{/* Optionally hide name on smaller desktop screens */}
<span className="text-sm font-medium text-foreground hidden lg:inline">
{session.user.name?.split(" ")[0]}
</span>
</div>
}
>
{/* Sign Out inside the dropdown */}
<button
onClick={() => handleSignOut()}
className="block w-full text-left px-4 py-2 text-sm text-destructive hover:bg-secondary hover:text-destructive transition" // Destructive color
>
Sign Out
</button>
</DropdownMenu>
) : (
// Logged Out: Icon Button to Sign In
<button
onClick={() => handleSignIn()}
className="p-2 rounded-full text-foreground/70 hover:text-primary hover:bg-secondary focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background transition-colors"
title="Sign In"
aria-label="Sign In"
>
<FiLogIn className="w-5 h-5" />
</button>
)}
{/* --- End Auth Section --- */}
</div>
{/* Mobile Buttons */}
<div className="md:hidden flex items-center">
<ThemeToggle /> {/* Theme toggle remains */}
<button
onClick={toggleMenu}
className="text-foreground/60 hover:text-primary focus:outline-none ml-3" // Use semantic muted color, hover primary
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
aria-controls="mobile-menu"
>
{isMenuOpen ? (
<FiX className="w-6 h-6" />
) : (
<FiMenu className="w-6 h-6" />
)}
</button>
</div>
</div>
</div>
{/* Secondary Row (Desktop Only) */}
<div className="bg-primary">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="hidden md:flex justify-between items-center h-12">
<nav className="flex items-center space-x-6 lg:space-x-8 text-primary-foreground">
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Services</span>}>
<DropdownLink href="/services/resource-augmentation">
Resource Augmentation
</DropdownLink>
<DropdownLink href="/services/project-management">
Project Management
</DropdownLink>
<DropdownLink href="/services/product-development">
Product Development
</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Products</span>}>
<DropdownLink href="/products/obse">OBSE</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Join Our Team</span>}>
<DropdownLink href="/join-us/vacancies">
Vacancies
</DropdownLink>
<DropdownLink href="/join-us/portal">
Recruitment Portal
</DropdownLink>
</DropdownMenu>
</div>
</nav>
<Link
href="/services"
className="flex items-center text-sm font-medium text-primary-foreground hover:text-opacity-80 transition-opacity group"
>
Explore Our Offerings
<FiArrowRight className="w-4 h-4 ml-1.5 transition-transform duration-200 group-hover:translate-x-1" />
</Link>
</div>
</div>
</div>
{/* Mobile Menu Panel */}
<div
id="mobile-menu"
// Use semantic variables for background and border
className={`md:hidden absolute top-full left-0 w-full shadow-lg transition-all duration-300 ease-in-out overflow-hidden bg-card border-t border-border ${
isMenuOpen
? "max-h-[calc(100vh-4rem)] py-4 overflow-y-auto"
: "max-h-0 py-0" // Animate height, allow scroll
}`}
>
{/* Use semantic variable for text color */}
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-1 text-foreground">
{" "}
{/* Reduced space-y */}
{/* Mobile Links */}
<DropdownLink href="/" onClick={handleMobileLinkClick}>
Home
</DropdownLink>
<DropdownLink href="/about" onClick={handleMobileLinkClick}>
About Us
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Services
</span>
<DropdownLink
href="/services/resource-augmentation"
onClick={handleMobileLinkClick}
>
Resource Augmentation
</DropdownLink>
<DropdownLink
href="/services/project-management"
onClick={handleMobileLinkClick}
>
Project Management
</DropdownLink>
<DropdownLink
href="/services/product-development"
onClick={handleMobileLinkClick}
>
Product Development
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Products
</span>
<DropdownLink href="/products/obse" onClick={handleMobileLinkClick}>
OBSE
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Join Us
</span>
<DropdownLink
href="/join-us/vacancies"
onClick={handleMobileLinkClick}
>
Vacancies
</DropdownLink>
<DropdownLink href="/join-us/portal" onClick={handleMobileLinkClick}>
Recruitment Portal
</DropdownLink>
<DropdownLink href="/contact" onClick={handleMobileLinkClick}>
Contact Us
</DropdownLink>
{/* Demo Button */}
<div className="pt-4">
<Link
href="/request-demo"
onClick={handleMobileLinkClick}
// Use semantic variables for button style
className="flex w-full justify-center items-center text-sm font-medium bg-primary text-primary-foreground px-4 py-2 rounded-lg hover:bg-opacity-90 transition-colors"
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
Request Demo
</Link>
</div>
{/* Auth Buttons in Mobile Menu */}
<div className="pt-4 border-t border-border mt-4">
{session?.user ? (
// Sign Out Button (Text)
<button
onClick={() => {
handleSignOut();
handleMobileLinkClick();
}}
className="flex items-center w-full text-left px-4 py-2 text-sm font-medium text-destructive hover:bg-secondary transition"
>
Sign Out
</button>
) : (
// Sign In Button (Text or Icon+Text)
<button
onClick={() => {
handleSignIn();
handleMobileLinkClick();
}}
className="flex items-center w-full text-left px-4 py-2 text-sm font-medium text-foreground hover:bg-secondary hover:text-primary transition"
>
<FiLogIn className="w-4 h-4 mr-2" /> {/* Added icon here too */}
Sign In
</button>
)}
</div>
</nav>
</div>
</header>
);
};
export default HeaderClient;

View File

@ -1,7 +1,9 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
images: {
domains: ["avatars.githubusercontent.com"],
},
};
export default nextConfig;

BIN
public/images/partners.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
public/images/profile1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 KiB

BIN
public/images/profile2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/images/profile3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB