fix: ui tweaks including button styles, texts, and missing account link
This commit is contained in:
+7
-12
@@ -4,27 +4,23 @@ import { Header } from "@/components/layout/Header";
|
||||
import { TrustBar } from "@/components/layout/TrustBar";
|
||||
import { Footer } from "@/components/layout/Footer";
|
||||
import { CookieBanner } from "@/components/ui/CookieBanner";
|
||||
import { GoogleAnalytics, GoogleTagManager } from "@next/third-parties/google";
|
||||
import { AnalyticsWrapper } from "@/components/ui/AnalyticsWrapper";
|
||||
import "./globals.css";
|
||||
|
||||
const fontSans = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-sans",
|
||||
subsets: ["latin", "latin-ext"],
|
||||
});
|
||||
|
||||
const fontHeading = Poppins({
|
||||
variable: "--font-heading",
|
||||
subsets: ["latin"],
|
||||
weight: ["400", "500", "600", "700", "800"],
|
||||
subsets: ["latin", "latin-ext"],
|
||||
variable: "--font-heading",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
default: "Klimatyzacja, pompy ciepła i usługi domowe",
|
||||
template: "%s | HVAC & Usługi Domowe",
|
||||
},
|
||||
description: "Montaż klimatyzacji, pompy ciepła, remonty i hydraulika. Dobór, montaż i serwis. Darmowa konsultacja.",
|
||||
metadataBase: new URL("http://localhost:3000"),
|
||||
title: "ThermCool | Klimatyzacja i Pompy Ciepła",
|
||||
description: "Zapewniamy profesjonalny montaż klimatyzacji, pomp ciepła oraz kompleksowe usługi remontowo-wykończeniowe. Sprawdź naszą ofertę!",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -37,14 +33,13 @@ export default function RootLayout({
|
||||
lang="pl"
|
||||
className={`${fontSans.variable} ${fontHeading.variable} h-full antialiased`}
|
||||
>
|
||||
<GoogleTagManager gtmId="GTM-MBMRCD2N" />
|
||||
<body className="min-h-full flex flex-col bg-background text-foreground">
|
||||
<Header />
|
||||
<main className="flex-grow">{children}</main>
|
||||
<TrustBar />
|
||||
<Footer />
|
||||
<CookieBanner />
|
||||
<GoogleAnalytics gaId="G-1NGTSR4TWD" />
|
||||
<AnalyticsWrapper />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -176,11 +176,10 @@ export function ContactForm() {
|
||||
{errors.consent && <p className="text-red-500 text-xs font-medium">{errors.consent.message}</p>}
|
||||
</div>
|
||||
|
||||
{/* Button */}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-cta hover:bg-cta-hover text-white font-bold py-4 rounded-xl transition-colors flex items-center justify-center gap-2 disabled:opacity-70 disabled:cursor-not-allowed shadow-md"
|
||||
className="btn btn-primary w-full text-white font-bold py-4 h-auto rounded-xl flex items-center justify-center gap-2 shadow-md"
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from "next/link";
|
||||
import { Phone, Mail, MapPin, Clock, Facebook, Instagram, ShieldCheck } from "lucide-react";
|
||||
import { companyDetails } from "@/content/company";
|
||||
import { CookieSettingsTrigger } from "@/components/ui/CookieSettingsTrigger";
|
||||
|
||||
export function Footer() {
|
||||
const currentYear = new Date().getFullYear();
|
||||
@@ -136,10 +137,10 @@ export function Footer() {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Column 4: Account */}
|
||||
{/* Column 4: Obsługa Klienta */}
|
||||
<div>
|
||||
<h3 className="text-base font-semibold font-heading text-white mb-6 uppercase tracking-wider">
|
||||
Twoje Konto
|
||||
Obsługa Klienta
|
||||
</h3>
|
||||
<ul className="flex flex-col gap-3 text-sm text-slate-300">
|
||||
<li>
|
||||
@@ -165,9 +166,12 @@ export function Footer() {
|
||||
{/* Bottom Bar */}
|
||||
<div className="border-t border-slate-800 bg-slate-950/40 py-6">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col sm:flex-row justify-between items-center gap-4">
|
||||
<p className="text-xs text-slate-400 text-center sm:text-left">
|
||||
© {currentYear} {companyDetails.name}. Wszelkie prawa zastrzeżone. Projekt strony i wdrożenie ThermCool.
|
||||
</p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-xs text-slate-400 text-center sm:text-left">
|
||||
© {currentYear} {companyDetails.name}. Wszelkie prawa zastrzeżone. Projekt strony i wdrożenie ThermCool.
|
||||
</p>
|
||||
<CookieSettingsTrigger />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-6">
|
||||
{/* Social Icons */}
|
||||
|
||||
@@ -140,14 +140,6 @@ export function Header() {
|
||||
<div className="flex items-center gap-1">
|
||||
<GlobalSearch />
|
||||
|
||||
<Link
|
||||
href="/konto"
|
||||
className="p-2 text-primary hover:text-accent hover:bg-background rounded-lg transition-colors outline-none"
|
||||
aria-label="Konto użytkownika"
|
||||
>
|
||||
<User className="size-5" />
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/koszyk"
|
||||
className="p-2 text-primary hover:text-accent hover:bg-background rounded-lg transition-colors relative outline-none"
|
||||
|
||||
@@ -70,7 +70,7 @@ export function HeroSection({
|
||||
<ul className="mt-6 grid grid-cols-2 gap-3 text-white/90 font-medium">
|
||||
{features.map((feature, idx) => (
|
||||
<li key={idx} className="flex items-center gap-2">
|
||||
<Star className="size-4 text-accent fill-accent" />
|
||||
<Star className="size-4 text-yellow-400 fill-yellow-400" />
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
@@ -98,7 +98,7 @@ export function HeroSection({
|
||||
|
||||
{/* Trust Bar (Hero specific) */}
|
||||
<div className="mt-8 flex items-center gap-3 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center text-cta">
|
||||
<div className="flex items-center text-yellow-400">
|
||||
<Star className="size-4 fill-current" />
|
||||
<Star className="size-4 fill-current" />
|
||||
<Star className="size-4 fill-current" />
|
||||
|
||||
@@ -25,9 +25,9 @@ export function Testimonials() {
|
||||
|
||||
<div className="relative z-10 flex flex-col gap-4">
|
||||
{/* Stars */}
|
||||
<div className="flex gap-1 text-cta">
|
||||
<div className="flex gap-1 mb-4">
|
||||
{Array.from({ length: test.rating }).map((_, iIdx) => (
|
||||
<Star key={iIdx} className="size-4 fill-cta text-cta" />
|
||||
<Star key={iIdx} className="size-4 fill-yellow-400 text-yellow-400" />
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useConsentStore } from "@/lib/consent-store";
|
||||
import { GoogleAnalytics, GoogleTagManager } from "@next/third-parties/google";
|
||||
|
||||
export function AnalyticsWrapper() {
|
||||
const { analytics, marketing, isInitialized, initialize } = useConsentStore();
|
||||
|
||||
useEffect(() => {
|
||||
initialize();
|
||||
}, [initialize]);
|
||||
|
||||
if (!isInitialized) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Ładujemy GTM tylko jeśli zgoda na marketing ATAK LUB analitykę,
|
||||
w zależności od rygorystyczności, zazwyczaj GTM potrzebuje analityki/marketingu */}
|
||||
{(analytics || marketing) && <GoogleTagManager gtmId="GTM-MBMRCD2N" />}
|
||||
|
||||
{/* Ładujemy GA4 tylko jeśli użytkownik zgodził się na analitykę */}
|
||||
{analytics && <GoogleAnalytics gaId="G-1NGTSR4TWD" />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { useConsentStore } from "@/lib/consent-store";
|
||||
|
||||
export function CookieSettingsTrigger() {
|
||||
const openBanner = useConsentStore((state) => state.openBanner);
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={openBanner}
|
||||
className="text-slate-400 hover:text-accent transition-colors text-xs text-center sm:text-left underline underline-offset-2"
|
||||
>
|
||||
Zarządzaj plikami cookies
|
||||
</button>
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -126,7 +126,7 @@ export const homeProcessSteps: ProcessStep[] = [
|
||||
{
|
||||
number: 3,
|
||||
title: "Terminowa realizacja",
|
||||
description: "Wchodzimy na budowę w umówionym terminie. Dbamy o porządek i przestrzeganie norm budowlanych.",
|
||||
description: "Rozpoczynamy prace u klienta w umówionym terminie. Zabezpieczamy przestrzeń, dbamy o porządek i najwyższą jakość wykonania.",
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface ConsentState {
|
||||
isInitialized: boolean;
|
||||
isOpen: boolean;
|
||||
analytics: boolean;
|
||||
marketing: boolean;
|
||||
initialize: () => void;
|
||||
openBanner: () => void;
|
||||
closeBanner: () => void;
|
||||
setConsent: (analytics: boolean, marketing: boolean) => void;
|
||||
acceptAll: () => void;
|
||||
rejectOptional: () => void;
|
||||
}
|
||||
|
||||
const CONSENT_KEY = 'airproject_cookie_consent_v2';
|
||||
|
||||
export const useConsentStore = create<ConsentState>((set) => ({
|
||||
isInitialized: false,
|
||||
isOpen: false,
|
||||
analytics: false,
|
||||
marketing: false,
|
||||
|
||||
initialize: () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const stored = localStorage.getItem(CONSENT_KEY);
|
||||
if (stored) {
|
||||
try {
|
||||
const parsed = JSON.parse(stored);
|
||||
set({
|
||||
isInitialized: true,
|
||||
isOpen: false,
|
||||
analytics: !!parsed.analytics,
|
||||
marketing: !!parsed.marketing,
|
||||
});
|
||||
} catch (e) {
|
||||
// If parsing fails, show banner
|
||||
set({ isInitialized: true, isOpen: true });
|
||||
}
|
||||
} else {
|
||||
// No consent found, show banner
|
||||
set({ isInitialized: true, isOpen: true });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
openBanner: () => set({ isOpen: true }),
|
||||
|
||||
closeBanner: () => set({ isOpen: false }),
|
||||
|
||||
setConsent: (analytics, marketing) => {
|
||||
localStorage.setItem(CONSENT_KEY, JSON.stringify({ essential: true, analytics, marketing }));
|
||||
set({ analytics, marketing, isOpen: false });
|
||||
},
|
||||
|
||||
acceptAll: () => {
|
||||
localStorage.setItem(CONSENT_KEY, JSON.stringify({ essential: true, analytics: true, marketing: true }));
|
||||
set({ analytics: true, marketing: true, isOpen: false });
|
||||
},
|
||||
|
||||
rejectOptional: () => {
|
||||
localStorage.setItem(CONSENT_KEY, JSON.stringify({ essential: true, analytics: false, marketing: false }));
|
||||
set({ analytics: false, marketing: false, isOpen: false });
|
||||
}
|
||||
}));
|
||||
Reference in New Issue
Block a user