a78726303a
This commit updates the page metadata (title and description) from the default Next.js placeholders to be descriptive of the Opp lens application, improving SEO. Additionally, it refactors the HTML structure for better semantics and accessibility: - Replaced generic `div` and fragment tags with appropriate semantic elements like `main`, `article`, `li`, and `small`. - Corrected the heading hierarchy for better document structure. - Fixed image source paths by making them absolute to prevent broken images.
179 lines
4.8 KiB
TypeScript
179 lines
4.8 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { Geist, Geist_Mono } from "next/font/google";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { ToastContainer, Zoom } from "react-toastify";
|
|
import FooterForm from "../_components/FooterForm";
|
|
import "../globals.css";
|
|
const geistSans = Geist({
|
|
variable: "--font-geist-sans",
|
|
subsets: ["latin"],
|
|
});
|
|
|
|
const geistMono = Geist_Mono({
|
|
variable: "--font-geist-mono",
|
|
subsets: ["latin"],
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Opp lens - AI-Powered Tender Management",
|
|
description:
|
|
"Democratizing Tender Access for SMEs with AI-powered tender discovery and preparation.",
|
|
icons: {
|
|
icon: "/fav-icon.svg",
|
|
},
|
|
};
|
|
|
|
function ContactInfo({
|
|
icon,
|
|
contact,
|
|
href,
|
|
ariaLabel,
|
|
contactIconSrc,
|
|
}: {
|
|
icon: string;
|
|
contact: string;
|
|
href?: string;
|
|
ariaLabel: string;
|
|
contactIconSrc?: string;
|
|
}) {
|
|
return (
|
|
<li className="flex gap-3 my-3 text-white">
|
|
<Image
|
|
src={icon}
|
|
width={24}
|
|
height={24}
|
|
alt=""
|
|
aria-hidden="true"
|
|
/>
|
|
{href ? (
|
|
<a
|
|
href={href}
|
|
className="cursor-pointer min-w-fit"
|
|
aria-label={ariaLabel}>
|
|
{contact}
|
|
</a>
|
|
) : (
|
|
<p className="flex gap-3">
|
|
{!!contactIconSrc && (
|
|
<Image
|
|
src={contactIconSrc}
|
|
width={20}
|
|
height={20}
|
|
alt="flag"
|
|
/>
|
|
)}
|
|
{contact}
|
|
</p>
|
|
)}
|
|
</li>
|
|
);
|
|
}
|
|
|
|
export default async function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode;
|
|
}>) {
|
|
const contactInfo = [
|
|
{
|
|
icon: "/Message.svg",
|
|
contact: "info@opplens.com",
|
|
href: "mailto:info@opplens.com",
|
|
ariaLabel: "Email us at info@opplens.com",
|
|
},
|
|
{
|
|
icon: "/Phone.svg",
|
|
contact: "(+46) - 761581526",
|
|
href: "tel:+46761581526",
|
|
ariaLabel: "Call us at +46 761581526",
|
|
},
|
|
{
|
|
icon: "/Location.svg",
|
|
contact: "Stockholm, Sweden",
|
|
ariaLabel: "Our location in Stockholm, Sweden",
|
|
contactIconSrc: "/sweden.svg",
|
|
},
|
|
];
|
|
|
|
return (
|
|
<html lang="en">
|
|
<body
|
|
className={`${geistSans.variable} ${geistMono.variable} antialiased flex flex-col min-h-screen bg-[url('/header-bg.svg')] bg-top-right bg-no-repeat bg-contain`}>
|
|
<header className="flex justify-center pt-8 md:justify-between items-center pb-4 container px-4 py-4 m-auto">
|
|
<Link
|
|
href="/"
|
|
aria-label="Opp lens home">
|
|
<Image
|
|
src="/main-logo.svg"
|
|
alt="Opp lens logo"
|
|
width={180}
|
|
height={30}
|
|
priority
|
|
/>
|
|
</Link>
|
|
</header>
|
|
|
|
<ToastContainer
|
|
position="top-right"
|
|
autoClose={2500}
|
|
theme={"colored"}
|
|
transition={Zoom}
|
|
hideProgressBar
|
|
newestOnTop
|
|
closeOnClick
|
|
pauseOnFocusLoss
|
|
draggable
|
|
pauseOnHover
|
|
/>
|
|
|
|
<main className="container px-4 py-4 m-auto flex-grow">{children}</main>
|
|
<footer className="relative h-full bg-[url('/footer-bg.svg')] bg-cover bg-no-repeat mt-96">
|
|
<div
|
|
className="absolute w-full -top-[355px] md:-top-72 h-[600px] z-[-10] bg-[url('/bottom-bg.svg')] bg-contain bg-no-repeat bg-right"
|
|
aria-hidden="true"
|
|
/>
|
|
|
|
<FooterForm />
|
|
|
|
<div className="relative z-10 container px-4 py-4 m-auto flex flex-col justify-center items-center mt-96 ">
|
|
<div className="flex justify-between flex-col md:flex-row gap-14 w-full md:w-1/2">
|
|
<div className="flex flex-col gap-10">
|
|
<Image
|
|
src={"/footer-logo.svg"}
|
|
alt="Opp lens logo"
|
|
width={180}
|
|
height={30}
|
|
priority
|
|
/>
|
|
<div>
|
|
<p className="text-white my-2">
|
|
Democratizing Tender Access for SMEs.
|
|
</p>
|
|
<small className="text-white my-2">
|
|
© 2025 Opplens.com by PBL Partners AB. All Rights Reserved.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
<address className="not-italic">
|
|
<ul>
|
|
{contactInfo.map((contact, index) => (
|
|
<ContactInfo
|
|
key={index}
|
|
icon={contact.icon}
|
|
contact={contact.contact}
|
|
href={contact.href}
|
|
ariaLabel={contact.ariaLabel}
|
|
contactIconSrc={contact.contactIconSrc}
|
|
/>
|
|
))}
|
|
</ul>
|
|
</address>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|