Merge version_3 into main
Merge version_3 into main
This commit was merged in pull request #6.
This commit is contained in:
72
src/app/[locale]/layout.tsx
Normal file
72
src/app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import ReactLenis from "lenis/react";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import ProductCart from '@/components/ecommerce/cart/ProductCart';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
|
||||
import { Locale } from '@/lib/i18nConfig';
|
||||
|
||||
export default function LocaleLayout({
|
||||
children,
|
||||
}: Readonly<{ children: React.ReactNode }>)
|
||||
{
|
||||
const params = useParams();
|
||||
const locale = params.locale as Locale;
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-shift"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="medium"
|
||||
sizing="largeSmallSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="gradient-radial"
|
||||
primaryButtonStyle="shadow"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="bold"
|
||||
>
|
||||
<ReactLenis root>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
navItems={[
|
||||
{ name: "Home", id: `/${locale}` },
|
||||
{ name: "Vision", id: `#about` },
|
||||
{ name: "Services", id: `#product` },
|
||||
{ name: "Portfolio", id: `#team` },
|
||||
{ name: "Clients", id: `#testimonial` },
|
||||
{ name: "Contact", id: `#contact` },
|
||||
]}
|
||||
brandName="Enkidu Soft"
|
||||
button={{
|
||||
text: "Get in Touch", href: `#contact`
|
||||
}}
|
||||
animateOnLoad={true}
|
||||
>
|
||||
<LanguageSwitcher currentLocale={locale} />
|
||||
</NavbarLayoutFloatingInline>
|
||||
</div>
|
||||
{children}
|
||||
{/* The ProductCart is a global component, typically rendered within a layout. Moved here. */}
|
||||
<div id="ecommerce" data-section="ecommerce">
|
||||
<ProductCart
|
||||
isOpen={false}
|
||||
onClose={() => {}}
|
||||
items={[
|
||||
{
|
||||
id: "item1", name: "Sample Product", price: "99.99", quantity: 1,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Sample Product Image"
|
||||
}
|
||||
]}
|
||||
total="99.99"
|
||||
buttons={[
|
||||
{ text: "Checkout", onClick: () => console.log("Checkout clicked") }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
74
src/app/[locale]/page.tsx
Normal file
74
src/app/[locale]/page.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
"use client";
|
||||
|
||||
import SplitAbout from '@/components/sections/about/SplitAbout';
|
||||
import ProductCardThree from '@/components/sections/product/ProductCardThree';
|
||||
import TeamCardTwo from '@/components/sections/team/TeamCardTwo';
|
||||
import TestimonialCardFifteen from '@/components/sections/testimonial/TestimonialCardFifteen';
|
||||
|
||||
export default function LocalizedLandingPage() {
|
||||
return (
|
||||
<>
|
||||
<div id="about" data-section="about">
|
||||
<SplitAbout
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
imageSrc="http://img.b2bpic.net/free-photo/network-connections_1048-7667.jpg"
|
||||
imageAlt="Network connections"
|
||||
title="Our Story & Mission"
|
||||
description="We are a company dedicated to innovation and excellence, striving to deliver cutting-edge solutions for our clients."
|
||||
bulletPoints={[
|
||||
{ title: "Innovation driven", description: "Driving innovation across all our solutions." },
|
||||
{ title: "Client-focused", description: "Prioritizing client needs and delivering tailored results." },
|
||||
{ title: "Excellence in execution", description: "Committing to high-quality execution in every project." }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="product" data-section="product">
|
||||
<ProductCardThree
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
useInvertedBackground={false}
|
||||
title="Our Featured Products"
|
||||
description="Explore our range of innovative products designed to meet your needs."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="team" data-section="team">
|
||||
<TeamCardTwo
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
useInvertedBackground={false}
|
||||
title="Meet Our Team"
|
||||
description="A dedicated group of professionals passionate about technology and innovation."
|
||||
members={[
|
||||
{
|
||||
id: "john-doe", name: "John Doe", role: "CEO", imageSrc: "http://img.b2bpic.net/free-photo/focused-woman-working-with-ai-chatbot-her-desktop-computer_482257-120813.jpg", imageAlt: "John Doe, CEO", description: "Leading our company with vision and expertise."
|
||||
},
|
||||
{
|
||||
id: "jane-smith", name: "Jane Smith", role: "CTO", imageSrc: "http://img.b2bpic.net/free-photo/african-american-software-developer-does-visual-coding-creating-software_482257-127024.jpg", imageAlt: "Jane Smith, CTO", description: "Pioneering our technological advancements."
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="testimonial" data-section="testimonial">
|
||||
<TestimonialCardFifteen
|
||||
useInvertedBackground={false}
|
||||
testimonial="Working with this team has been a game-changer for our business. Their expertise and dedication are unmatched."
|
||||
rating={5}
|
||||
ratingAnimation="slide-up"
|
||||
author="Alice Johnson"
|
||||
avatars={[
|
||||
{
|
||||
src: "http://img.b2bpic.net/free-photo/focused-woman-working-with-ai-chatbot-her-desktop-computer_482257-120813.jpg", alt: "Alice Johnson"
|
||||
}
|
||||
]}
|
||||
avatarsAnimation="slide-up"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,36 +1,25 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Halant } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import { Public_Sans } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import "@/lib/gsap-setup";
|
||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
||||
import Tag from "@/tag/Tag";
|
||||
import { getVisualEditScript } from "@/utils/visual-edit-script";
|
||||
import { Public_Sans } from "next/font/google";
|
||||
|
||||
|
||||
import { i18n } from '@/lib/i18nConfig'; // New import
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Enkidu Soft - Engineering Excellence',
|
||||
description: 'Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.',
|
||||
openGraph: {
|
||||
"title": "Enkidu Soft - Engineering Excellence",
|
||||
"description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.",
|
||||
"url": "https://www.enkidusoft.com/en",
|
||||
"siteName": "Enkidu Soft",
|
||||
"images": [
|
||||
"title": "Enkidu Soft - Engineering Excellence", "description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.", "url": "https://www.enkidusoft.com/en", "siteName": "Enkidu Soft", "images": [
|
||||
{
|
||||
"url": "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg",
|
||||
"alt": "Abstract data flow and secure connections"
|
||||
"url": "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg", "alt": "Abstract data flow and secure connections"
|
||||
}
|
||||
],
|
||||
"type": "website"
|
||||
},
|
||||
twitter: {
|
||||
"card": "summary_large_image",
|
||||
"title": "Enkidu Soft - Engineering Excellence",
|
||||
"description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.",
|
||||
"images": [
|
||||
"card": "summary_large_image", "title": "Enkidu Soft - Engineering Excellence", "description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.", "images": [
|
||||
"http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg"
|
||||
]
|
||||
},
|
||||
@@ -41,17 +30,23 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
const publicSans = Public_Sans({
|
||||
variable: "--font-public-sans",
|
||||
subsets: ["latin"],
|
||||
variable: "--font-public-sans", subsets: ["latin"],
|
||||
});
|
||||
|
||||
// Generate static params for all locales
|
||||
export function generateStaticParams() {
|
||||
return i18n.locales.map((locale) => ({ locale }));
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
params: { locale }, // Accept locale from the URL
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
params: { locale: string }; // Type definition for params
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<html lang={locale} dir={locale === 'ar' ? 'rtl' : 'ltr'} suppressHydrationWarning>
|
||||
<ServiceWrapper>
|
||||
<body className={`${publicSans.variable} antialiased`}>
|
||||
<Tag />
|
||||
|
||||
@@ -4,10 +4,11 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import ReactLenis from "lenis/react";
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import ProductCardThree from '@/components/sections/product/ProductCardThree';
|
||||
import ProductCart from '@/components/ecommerce/cart/ProductCart';
|
||||
import SplitAbout from '@/components/sections/about/SplitAbout';
|
||||
import TeamCardTwo from '@/components/sections/team/TeamCardTwo';
|
||||
import TestimonialCardFifteen from '@/components/sections/testimonial/TestimonialCardFifteen';
|
||||
import SocialProofOne from '@/components/sections/socialProof/SocialProofOne';
|
||||
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
||||
|
||||
export default function LandingPage() {
|
||||
return (
|
||||
@@ -63,14 +64,35 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="product" data-section="product">
|
||||
<div id="portfolio" data-section="portfolio">
|
||||
<ProductCardThree
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
gridVariant="bento-grid"
|
||||
useInvertedBackground={false}
|
||||
title="Our Featured Products"
|
||||
description="Explore our range of innovative products designed to meet your needs."
|
||||
title="Our Portfolio Showcase"
|
||||
description="Discover our diverse projects and the impact we've made."
|
||||
products={[
|
||||
{ id: "p1", name: "Enterprise CRM", price: "Software Development", imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Enterprise CRM project" },
|
||||
{ id: "p2", name: "AI-Powered Analytics", price: "AI & Data Science", imageSrc: "http://img.b2bpic.net/free-photo/network-connections_1048-7667.jpg", imageAlt: "AI-Powered Analytics project" },
|
||||
{ id: "p3", name: "Fintech Platform", price: "Fintech Solutions", imageSrc: "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg", imageAlt: "Fintech Platform project" },
|
||||
{ id: "p4", name: "Mobile E-commerce App", price: "Mobile Development", imageSrc: "http://img.b2bpic.net/free-photo/close-up-of-business-man-using-laptop_1048-18305.jpg", imageAlt: "Mobile E-commerce App project" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="clients" data-section="clients">
|
||||
<SocialProofOne
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
title="Trusted by Industry Leaders"
|
||||
description="We partner with leading organizations to drive innovation and growth."
|
||||
names={[
|
||||
"TechCorp", "Innovate Global", "Future Solutions", "Dynamic Systems", "Quantum Leap", "Synergy Corp", "Global Dynamics"
|
||||
]}
|
||||
showCard={false}
|
||||
speed={30}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -108,19 +130,19 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="ecommerce" data-section="ecommerce">
|
||||
<ProductCart
|
||||
isOpen={false}
|
||||
onClose={() => {}}
|
||||
items={[
|
||||
{
|
||||
id: "item1", name: "Sample Product", price: "99.99", quantity: 1,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Sample Product Image"}
|
||||
]}
|
||||
total="99.99"
|
||||
buttons={[
|
||||
{ text: "Checkout", onClick: () => console.log("Checkout clicked") }
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactSplitForm
|
||||
title="Partner with Us"
|
||||
description="Ready to transform your enterprise? Get in touch with our experts today."
|
||||
inputs={[
|
||||
{ name: "name", type: "text", placeholder: "Your Name", required: true },
|
||||
{ name: "email", type: "email", placeholder: "Your Email", required: true },
|
||||
{ name: "company", type: "text", placeholder: "Your Company" }
|
||||
]}
|
||||
textarea={{ name: "message", placeholder: "Your message...", rows: 5, required: false }}
|
||||
buttonText="Send Message"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/contact-us-customer-service-concept-man-using-laptop_23-2149454178.jpg"
|
||||
imageAlt="Contact us"
|
||||
/>
|
||||
</div>
|
||||
</ReactLenis>
|
||||
|
||||
63
src/components/LanguageSwitcher.tsx
Normal file
63
src/components/LanguageSwitcher.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, usePathname } from 'next/navigation';
|
||||
import { i18n, Locale } from '@/lib/i18nConfig';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; // Assuming shadcn-ui select component
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
// Placeholder for shadcn-ui select if not available:
|
||||
// Replace with your actual UI kit's Select/Dropdown or a simple <select> element.
|
||||
// If you don't have shadcn-ui, you might need to create these components or adjust imports.
|
||||
// For example, a basic HTML select:
|
||||
/*
|
||||
const BasicSelect = ({ value, onChange, options, placeholder }) => (
|
||||
<select value={value} onChange={(e) => onChange(e.target.value)}>
|
||||
{placeholder && <option value="" disabled>{placeholder}</option>}
|
||||
{options.map((option) => (
|
||||
<option key={option.value} value={option.value}>{option.label}</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
*/
|
||||
|
||||
interface LanguageSwitcherProps {
|
||||
currentLocale: Locale;
|
||||
}
|
||||
|
||||
export function LanguageSwitcher({ currentLocale }: LanguageSwitcherProps) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
|
||||
if (!isMounted) {
|
||||
return null; // Or a loading spinner
|
||||
}
|
||||
|
||||
const onSelectChange = (newLocale: Locale) => {
|
||||
// Replace the current locale in the pathname with the new one
|
||||
const newPath = `/${newLocale}${pathname.substring(3)}`; // Assuming /en, /fr, /es are 3 chars
|
||||
router.push(newPath);
|
||||
|
||||
// Set cookie for middleware to remember preferred locale
|
||||
document.cookie = `NEXT_LOCALE=${newLocale}; path=/; max-age=31536000;`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Select onValueChange={onSelectChange} defaultValue={currentLocale}>
|
||||
<SelectTrigger className="w-[100px] bg-background-accent text-foreground">
|
||||
<SelectValue placeholder="Language" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-card text-foreground">
|
||||
{i18n.locales.map((locale) => (
|
||||
<SelectItem key={locale} value={locale}>
|
||||
{locale.toUpperCase()}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
6
src/lib/i18nConfig.ts
Normal file
6
src/lib/i18nConfig.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const i18n = {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr', 'es'], // Define your supported locales
|
||||
} as const;
|
||||
|
||||
export type Locale = (typeof i18n)['locales'][number];
|
||||
38
src/middleware.ts
Normal file
38
src/middleware.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { i18n } from './lib/i18nConfig';
|
||||
|
||||
const PUBLIC_FILE_REGEX = /\.(.*)$/;
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
const locale = request.cookies.get('NEXT_LOCALE')?.value || i18n.defaultLocale;
|
||||
const { pathname } = request.nextUrl;
|
||||
|
||||
// Skip internal Next.js paths and static files
|
||||
if (
|
||||
pathname.startsWith('/_next') ||
|
||||
pathname.startsWith('/api') ||
|
||||
PUBLIC_FILE_REGEX.test(pathname)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there is any supported locale in the pathname
|
||||
const pathnameHasLocale = i18n.locales.some(
|
||||
(loc) => pathname.startsWith(`/${loc}/`) || pathname === `/${loc}`
|
||||
);
|
||||
|
||||
if (pathnameHasLocale) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// Rewrite to include the default locale if no locale is present
|
||||
request.nextUrl.pathname = `/${locale}${pathname}`;
|
||||
return NextResponse.redirect(request.nextUrl);
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/((?!api|_next/static|_next/image|favicon.ico).*)',
|
||||
'/',
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user