Fix heading structure (H1-H6) and button layouts, add noindex to cart and order pages

This commit is contained in:
MichalC
2026-07-19 20:42:06 +02:00
parent c7dcbab6c0
commit acf6269f32
26 changed files with 484 additions and 82 deletions
+8 -6
View File
@@ -3,6 +3,8 @@ import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Check, Phone, ArrowRight, Wrench, Zap, Wind } from 'lucide-react'; import { Check, Phone, ArrowRight, Wrench, Zap, Wind } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Cennik montażu klimatyzacji Wrocław 2026 — ile kosztuje montaż?', title: 'Cennik montażu klimatyzacji Wrocław 2026 — ile kosztuje montaż?',
@@ -136,11 +138,11 @@ export default function CennikMontazuPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4"> <div className="flex flex-col sm:flex-row gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md">
<Phone className="size-5" /> Zadzwoń po wycenę <Phone className="size-5" /> Zadzwoń po wycenę
</button> </Button>
</a> </a>
<Link href="/kontakt" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kontakt" className={buttonClasses({ variant: 'outline', size: 'md' })}>
Formularz kontaktowy <ArrowRight className="size-5" /> Formularz kontaktowy <ArrowRight className="size-5" />
@@ -247,11 +249,11 @@ export default function CennikMontazuPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kontakt" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kontakt" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Napisz do nas <ArrowRight className="size-5" /> Napisz do nas <ArrowRight className="size-5" />
+8 -6
View File
@@ -3,6 +3,8 @@ import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Check, Phone, Wrench, ArrowRight, Building2, Thermometer, Wind, Zap, Clock } from 'lucide-react'; import { Check, Phone, Wrench, ArrowRight, Building2, Thermometer, Wind, Zap, Clock } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Klimatyzacja do biura Wrocław — montaż, serwis', title: 'Klimatyzacja do biura Wrocław — montaż, serwis',
@@ -135,11 +137,11 @@ export default function KlimatyzacjaDoBiuraPage() {
<div className="flex flex-col sm:flex-row gap-4"> <div className="flex flex-col sm:flex-row gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kontakt" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kontakt" className={buttonClasses({ variant: 'outline', size: 'md' })}>
Zapytaj o wycenę dla firmy <ArrowRight className="size-5" /> Zapytaj o wycenę dla firmy <ArrowRight className="size-5" />
@@ -273,11 +275,11 @@ export default function KlimatyzacjaDoBiuraPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kontakt" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kontakt" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Napisz do nas <ArrowRight className="size-5" /> Napisz do nas <ArrowRight className="size-5" />
+8 -6
View File
@@ -3,6 +3,8 @@ import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Check, Phone, Wrench, ArrowRight, Home, Thermometer, Wind, Zap } from 'lucide-react'; import { Check, Phone, Wrench, ArrowRight, Home, Thermometer, Wind, Zap } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Klimatyzacja do domu Wrocław — montaż split i multisplit', title: 'Klimatyzacja do domu Wrocław — montaż split i multisplit',
@@ -113,11 +115,11 @@ export default function KlimatyzacjaDoDomuPage() {
<div className="flex flex-col sm:flex-row gap-4"> <div className="flex flex-col sm:flex-row gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kalkulator" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kalkulator" className={buttonClasses({ variant: 'outline', size: 'md' })}>
Dobierz urządzenie <ArrowRight className="size-5" /> Dobierz urządzenie <ArrowRight className="size-5" />
@@ -242,11 +244,11 @@ export default function KlimatyzacjaDoDomuPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kalkulator" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kalkulator" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Kalkulator doboru <ArrowRight className="size-5" /> Kalkulator doboru <ArrowRight className="size-5" />
+17
View File
@@ -0,0 +1,17 @@
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Koszyk',
robots: {
index: false,
follow: true,
},
};
export default function KoszykLayout({
children,
}: {
children: React.ReactNode;
}) {
return <>{children}</>;
}
+4 -2
View File
@@ -4,6 +4,8 @@ import { useCartStore } from '@/lib/cart-store';
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { Trash2, Plus, Minus, ShoppingBag, ArrowRight } from 'lucide-react'; import { Trash2, Plus, Minus, ShoppingBag, ArrowRight } from 'lucide-react';
import { buttonClasses } from '@/components/ui/Button';
export default function KoszykPage() { export default function KoszykPage() {
const { items, removeItem, updateQuantity, getTotal, clearCart } = useCartStore(); const { items, removeItem, updateQuantity, getTotal, clearCart } = useCartStore();
@@ -14,9 +16,9 @@ export default function KoszykPage() {
<main className="min-h-screen bg-slate-50 flex items-center justify-center"> <main className="min-h-screen bg-slate-50 flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<ShoppingBag className="size-16 text-border mx-auto mb-4" /> <ShoppingBag className="size-16 text-border mx-auto mb-4" />
<h1 className="text-2xl font-bold text-primary font-heading mb-2">Koszyk jest pusty</h1> <h2 className="text-2xl font-bold text-primary font-heading mb-2">Koszyk jest pusty</h2>
<p className="text-text-muted mb-6">Dodaj produkty ze sklepu aby złożyć zamówienie.</p> <p className="text-text-muted mb-6">Dodaj produkty ze sklepu aby złożyć zamówienie.</p>
<Link href="/sklep" className="btn btn-primary text-white font-bold"> <Link href="/sklep" className={buttonClasses({ variant: 'primary', size: 'md' })}>
Przejdź do sklepu Przejdź do sklepu
</Link> </Link>
</div> </div>
+7 -5
View File
@@ -3,6 +3,8 @@ import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Check, Phone, Wrench, ArrowRight, ShieldCheck, Clock, Star } from 'lucide-react'; import { Check, Phone, Wrench, ArrowRight, ShieldCheck, Clock, Star } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Montaż klimatyzacji Wrocław — split, multisplit', title: 'Montaż klimatyzacji Wrocław — split, multisplit',
@@ -113,11 +115,11 @@ export default function MontazKlimatyzacjiPage() {
<div className="flex flex-col sm:flex-row gap-4"> <div className="flex flex-col sm:flex-row gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kalkulator" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kalkulator" className={buttonClasses({ variant: 'outline', size: 'md' })}>
Dobierz urządzenie <ArrowRight className="size-5" /> Dobierz urządzenie <ArrowRight className="size-5" />
@@ -250,9 +252,9 @@ export default function MontazKlimatyzacjiPage() {
Zadzwoń po bezpłatną wycenę — odpowiadamy szybko i przyjeżdżamy w całym Dolnym Śląsku. Zadzwoń po bezpłatną wycenę — odpowiadamy szybko i przyjeżdżamy w całym Dolnym Śląsku.
</p> </p>
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors mx-auto"> <Button variant="primary" size="lg" className="mx-auto">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
</div> </div>
</section> </section>
+3 -1
View File
@@ -1,4 +1,6 @@
import Link from 'next/link'; import Link from 'next/link';
import { buttonClasses } from '@/components/ui/Button';
export default function NotFound() { export default function NotFound() {
return ( return (
@@ -9,7 +11,7 @@ export default function NotFound() {
<p className="text-base md:text-lg text-slate-500 mb-8 max-w-md mx-auto"> <p className="text-base md:text-lg text-slate-500 mb-8 max-w-md mx-auto">
Szukana strona została usunięta lub nigdy nie istniała. Szukana strona została usunięta lub nigdy nie istniała.
</p> </p>
<Link href="/" className="btn btn-primary text-white font-bold"> <Link href="/" className={buttonClasses({ variant: 'primary', size: 'md' })}>
Wróć na stronę główną Wróć na stronę główną
</Link> </Link>
</div> </div>
+6 -5
View File
@@ -9,6 +9,7 @@ import { CtaBanner } from "@/components/sections/CtaBanner";
import { companyDetails } from "@/content/company"; import { companyDetails } from "@/content/company";
import { Wrench, Phone, ArrowRight, Thermometer, Wind, Zap, Calendar, Check } from "lucide-react"; import { Wrench, Phone, ArrowRight, Thermometer, Wind, Zap, Calendar, Check } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { Button, buttonClasses } from "@/components/ui/Button";
export default function Home() { export default function Home() {
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://thermcool.pl'; const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://thermcool.pl';
@@ -160,16 +161,16 @@ export default function Home() {
na terenie całego Dolnego Śląska. na terenie całego Dolnego Śląska.
</p> </p>
</div> </div>
<div className="flex flex-col gap-3 shrink-0"> <div className="inline-flex flex-col gap-3 shrink-0">
<Link href="/serwis-lg" className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors whitespace-nowrap"> <Link href="/serwis-lg" className={buttonClasses({ variant: 'primary', size: 'md', className: 'w-full' })}>
Dowiedz się więcej <ArrowRight className="size-4" /> Dowiedz się więcej <ArrowRight className="size-4" />
</Link> </Link>
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`} className="w-full">
<button className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20 whitespace-nowrap"> <Button variant="outline" size="md" className="w-full">
<Phone className="size-4" /> Zadzwoń teraz <Phone className="size-4" /> Zadzwoń teraz
</button> </Button>
</a> </a>
</div> </div>
</div> </div>
+3 -1
View File
@@ -5,6 +5,8 @@ import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { X, ShoppingCart } from 'lucide-react'; import { X, ShoppingCart } from 'lucide-react';
import { useCartStore } from '@/lib/cart-store'; import { useCartStore } from '@/lib/cart-store';
import { buttonClasses } from '@/components/ui/Button';
export default function PorownajPage() { export default function PorownajPage() {
const { items, removeItem } = useCompareStore(); const { items, removeItem } = useCompareStore();
@@ -15,7 +17,7 @@ export default function PorownajPage() {
<main className="min-h-screen bg-slate-50 flex items-center justify-center"> <main className="min-h-screen bg-slate-50 flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<p className="text-text-muted mb-4">Nie masz żadnych produktów do porównania.</p> <p className="text-text-muted mb-4">Nie masz żadnych produktów do porównania.</p>
<Link href="/sklep" className="btn btn-primary text-white font-bold"> <Link href="/sklep" className={buttonClasses({ variant: 'primary', size: 'md' })}>
Wróć do sklepu Wróć do sklepu
</Link> </Link>
</div> </div>
+10 -8
View File
@@ -2,6 +2,8 @@ import type { Metadata } from 'next';
import Link from 'next/link'; import Link from 'next/link';
import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react'; import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Serwis klimatyzacji Daikin Wrocław — naprawa i przegląd', title: 'Serwis klimatyzacji Daikin Wrocław — naprawa i przegląd',
@@ -88,13 +90,13 @@ export default function SerwisDaikinPage() {
Serwisujemy wszystkie serie — od Sensiry po systemy VRV — z użyciem oryginalnych części Serwisujemy wszystkie serie — od Sensiry po systemy VRV — z użyciem oryginalnych części
i pełną dokumentacją przeglądową. i pełną dokumentacją przeglądową.
</p> </p>
<div className="flex flex-col sm:flex-row gap-4"> <div className="inline-flex flex-col gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`} className="w-full">
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md" className="w-full">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'md', className: 'w-full' })}>
Zgłoś awarię online <ArrowRight className="size-5" /> Zgłoś awarię online <ArrowRight className="size-5" />
@@ -193,11 +195,11 @@ export default function SerwisDaikinPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Zgłoś online <ArrowRight className="size-5" /> Zgłoś online <ArrowRight className="size-5" />
+8 -6
View File
@@ -3,6 +3,8 @@ import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Check, Phone, Wrench, ArrowRight, Thermometer, Wind, Zap, ShieldCheck } from 'lucide-react'; import { Check, Phone, Wrench, ArrowRight, Thermometer, Wind, Zap, ShieldCheck } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Serwis klimatyzacji Wrocław — przegląd, czyszczenie, naprawa', title: 'Serwis klimatyzacji Wrocław — przegląd, czyszczenie, naprawa',
@@ -146,11 +148,11 @@ export default function SerwisKlimatyzacjiPage() {
<div className="flex flex-col sm:flex-row gap-4"> <div className="flex flex-col sm:flex-row gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'md' })}>
Zgłoś awarię online <ArrowRight className="size-5" /> Zgłoś awarię online <ArrowRight className="size-5" />
@@ -231,11 +233,11 @@ export default function SerwisKlimatyzacjiPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Zgłoś online <ArrowRight className="size-5" /> Zgłoś online <ArrowRight className="size-5" />
+9 -7
View File
@@ -2,6 +2,8 @@ import type { Metadata } from 'next';
import Link from 'next/link'; import Link from 'next/link';
import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react'; import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Serwis klimatyzacji LG Wrocław — naprawa i przegląd', title: 'Serwis klimatyzacji LG Wrocław — naprawa i przegląd',
@@ -84,13 +86,13 @@ export default function SerwisLGPage() {
My mamy odpowiednie doświadczenie i narzędzia, żeby skutecznie diagnozować My mamy odpowiednie doświadczenie i narzędzia, żeby skutecznie diagnozować
i naprawiać te urządzenia na terenie Dolnego Śląska. i naprawiać te urządzenia na terenie Dolnego Śląska.
</p> </p>
<div className="flex flex-col sm:flex-row gap-4"> <div className="inline-flex flex-col gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`} className="w-full">
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md" className="w-full">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/kontakt" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/kontakt" className={buttonClasses({ variant: 'outline', size: 'md', className: 'w-full' })}>
Napisz do nas <ArrowRight className="size-5" /> Napisz do nas <ArrowRight className="size-5" />
@@ -188,9 +190,9 @@ export default function SerwisLGPage() {
Zadzwoń lub napisz — odpowiadamy szybko i przyjeżdżamy na Dolny Śląsk. Zadzwoń lub napisz — odpowiadamy szybko i przyjeżdżamy na Dolny Śląsk.
</p> </p>
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors mx-auto"> <Button variant="primary" size="lg" className="mx-auto">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
</div> </div>
</section> </section>
+10 -8
View File
@@ -2,6 +2,8 @@ import type { Metadata } from 'next';
import Link from 'next/link'; import Link from 'next/link';
import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react'; import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Serwis klimatyzacji Mitsubishi Electric Wrocław — naprawa i przegląd', title: 'Serwis klimatyzacji Mitsubishi Electric Wrocław — naprawa i przegląd',
@@ -88,13 +90,13 @@ export default function SerwisMitsubishiPage() {
wszystkie serie — MSZ, MXZ, MLZ, SEZ — z pełną dokumentacją przeglądową wszystkie serie — MSZ, MXZ, MLZ, SEZ — z pełną dokumentacją przeglądową
i oryginalnymi częściami zamiennymi. i oryginalnymi częściami zamiennymi.
</p> </p>
<div className="flex flex-col sm:flex-row gap-4"> <div className="inline-flex flex-col gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`} className="w-full">
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md" className="w-full">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'md', className: 'w-full' })}>
Zgłoś awarię online <ArrowRight className="size-5" /> Zgłoś awarię online <ArrowRight className="size-5" />
@@ -197,11 +199,11 @@ export default function SerwisMitsubishiPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Zgłoś online <ArrowRight className="size-5" /> Zgłoś online <ArrowRight className="size-5" />
+10 -8
View File
@@ -2,6 +2,8 @@ import type { Metadata } from 'next';
import Link from 'next/link'; import Link from 'next/link';
import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react'; import { Check, Phone, Wrench, AlertTriangle, ArrowRight } from 'lucide-react';
import { companyDetails } from '@/content/company'; import { companyDetails } from '@/content/company';
import { buttonClasses, Button } from '@/components/ui/Button';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Serwis klimatyzacji Samsung Wrocław — naprawa i przegląd', title: 'Serwis klimatyzacji Samsung Wrocław — naprawa i przegląd',
@@ -88,13 +90,13 @@ export default function SerwisSamsungPage() {
Serwisujemy wszystkie serie — WindFree, Luzon, Maldives i inne — z szybkim terminem Serwisujemy wszystkie serie — WindFree, Luzon, Maldives i inne — z szybkim terminem
i precyzyjną diagnostyką elektroniczną. i precyzyjną diagnostyką elektroniczną.
</p> </p>
<div className="flex flex-col sm:flex-row gap-4"> <div className="inline-flex flex-col gap-4">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`} className="w-full">
<button className="flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent/90 transition-colors"> <Button variant="primary" size="md" className="w-full">
<Phone className="size-5" /> Zadzwoń: {companyDetails.phone} <Phone className="size-5" /> Zadzwoń: {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-6 py-3 bg-white/10 text-white rounded-xl font-bold hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'md', className: 'w-full' })}>
Zgłoś awarię online <ArrowRight className="size-5" /> Zgłoś awarię online <ArrowRight className="size-5" />
@@ -193,11 +195,11 @@ export default function SerwisSamsungPage() {
</p> </p>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href={`tel:${companyDetails.phoneRaw}`}> <a href={`tel:${companyDetails.phoneRaw}`}>
<button className="flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent/90 transition-colors"> <Button variant="primary" size="lg">
<Phone className="size-5" /> {companyDetails.phone} <Phone className="size-5" /> {companyDetails.phone}
</button> </Button>
</a> </a>
<Link href="/zgloszenie-awarii" className="flex items-center gap-2 px-8 py-4 bg-white/10 text-white rounded-xl font-bold text-lg hover:bg-white/20 transition-colors border border-white/20"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'outline', size: 'lg' })}>
Zgłoś online <ArrowRight className="size-5" /> Zgłoś online <ArrowRight className="size-5" />
+17
View File
@@ -0,0 +1,17 @@
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Zamówienie',
robots: {
index: false,
follow: true,
},
};
export default function ZamowienieLayout({
children,
}: {
children: React.ReactNode;
}) {
return <>{children}</>;
}
+5 -3
View File
@@ -5,6 +5,8 @@ import { useActionState, useEffect } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import { submitOrderForm } from './actions'; import { submitOrderForm } from './actions';
import { ArrowLeft, CheckCircle } from 'lucide-react'; import { ArrowLeft, CheckCircle } from 'lucide-react';
import { buttonClasses } from '@/components/ui/Button';
const initialState = { success: false, message: '' }; const initialState = { success: false, message: '' };
@@ -22,7 +24,7 @@ export default function ZamowieniePage() {
<main className="min-h-screen bg-slate-50 flex items-center justify-center"> <main className="min-h-screen bg-slate-50 flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<p className="text-text-muted mb-4">Koszyk jest pusty.</p> <p className="text-text-muted mb-4">Koszyk jest pusty.</p>
<Link href="/sklep" className="btn btn-primary text-white font-bold"> <Link href="/sklep" className={buttonClasses({ variant: 'primary', size: 'md' })}>
Wróć do sklepu Wróć do sklepu
</Link> </Link>
</div> </div>
@@ -35,9 +37,9 @@ Wróć do sklepu
<main className="min-h-screen bg-slate-50 flex items-center justify-center"> <main className="min-h-screen bg-slate-50 flex items-center justify-center">
<div className="text-center max-w-md px-4"> <div className="text-center max-w-md px-4">
<CheckCircle className="size-16 text-green-500 mx-auto mb-4" /> <CheckCircle className="size-16 text-green-500 mx-auto mb-4" />
<h1 className="text-2xl font-bold text-primary font-heading mb-2">Zamówienie przyjęte!</h1> <h2 className="text-2xl font-bold text-primary font-heading mb-2">Zamówienie przyjęte!</h2>
<p className="text-text-muted mb-6">{state.message}</p> <p className="text-text-muted mb-6">{state.message}</p>
<Link href="/sklep" className="btn btn-primary text-white font-bold"> <Link href="/sklep" className={buttonClasses({ variant: 'primary', size: 'md' })}>
Wróć do sklepu Wróć do sklepu
</Link> </Link>
</div> </div>
+109
View File
@@ -0,0 +1,109 @@
const fs = require('fs');
const path = require('path');
function walkDir(dir, callback) {
if (!fs.existsSync(dir)) return;
fs.readdirSync(dir).forEach(f => {
const dirPath = path.join(dir, f);
const isDirectory = fs.statSync(dirPath).isDirectory();
if (isDirectory) {
walkDir(dirPath, callback);
} else if (dirPath.endsWith('.tsx')) {
callback(dirPath);
}
});
}
const appFiles = [];
const componentsFiles = [];
walkDir('app', f => appFiles.push(f));
walkDir('components', f => componentsFiles.push(f));
const allFiles = [...appFiles, ...componentsFiles];
const results = {};
allFiles.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const lines = content.split('\n');
const headings = [];
lines.forEach((line, index) => {
const regex = /<h([1-6])[\s>]/g;
let match;
while ((match = regex.exec(line)) !== null) {
headings.push({ level: parseInt(match[1]), line: index + 1, content: line.trim() });
}
});
if (headings.length > 0 || file.endsWith('page.tsx')) {
results[file] = headings;
}
});
// Analysis
console.log("=== HEADINGS AUDIT ===");
// 1. Pages with >1 H1
console.log("\n1. Strony z więcej niż jednym <h1>:");
let foundMultipleH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.includes('page.tsx')) {
const h1s = headings.filter(h => h.level === 1);
if (h1s.length > 1) {
console.log(`- ${file} (Liczba <h1>: ${h1s.length})`);
foundMultipleH1 = true;
}
}
}
if (!foundMultipleH1) console.log("Brak.");
// 2. Pages with 0 H1
console.log("\n2. Strony (page.tsx) bez <h1>:");
let foundZeroH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.includes('page.tsx') && !file.includes('api/')) { // ignoring api if any
const h1s = headings.filter(h => h.level === 1);
if (h1s.length === 0) {
console.log(`- ${file}`);
foundZeroH1 = true;
}
}
}
if (!foundZeroH1) console.log("Brak.");
// 3. Components rendering H1
console.log("\n3. Komponenty współdzielone (w components/) z <h1>:");
let foundComponentH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.startsWith('components/')) {
const h1s = headings.filter(h => h.level === 1);
if (h1s.length > 0) {
console.log(`- ${file} (${h1s.length} wystąpień <h1>)`);
foundComponentH1 = true;
}
}
}
if (!foundComponentH1) console.log("Brak.");
// 4. Heading Skips
console.log("\n4. Skoki poziomów nagłówków w plikach:");
let foundSkips = false;
for (const [file, headings] of Object.entries(results)) {
if (headings.length === 0) continue;
let currentLevel = null;
for (const h of headings) {
if (currentLevel !== null) {
// A skip happens if the new level is strictly greater than currentLevel + 1
if (h.level > currentLevel + 1) {
console.log(`- ${file}: Skok z <h${currentLevel}> na <h${h.level}> w linii ${h.line}`);
foundSkips = true;
}
}
currentLevel = h.level;
}
}
if (!foundSkips) console.log("Brak oczywistych skoków.");
+2 -2
View File
@@ -152,9 +152,9 @@ export function AwariaClient() {
<div className="size-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-6"> <div className="size-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-6">
<Check className="size-10 text-green-600" /> <Check className="size-10 text-green-600" />
</div> </div>
<h1 className="text-2xl font-extrabold text-primary font-heading mb-3"> <h2 className="text-2xl font-extrabold text-primary font-heading mb-3">
Zgłoszenie przyjęte! Zgłoszenie przyjęte!
</h1> </h2>
<p className="text-text-muted mb-2"> <p className="text-text-muted mb-2">
{isUrgent {isUrgent
? 'Twoje zgłoszenie oznaczono jako PILNE — skontaktujemy się z Tobą w ciągu 2 godzin.' ? 'Twoje zgłoszenie oznaczono jako PILNE — skontaktujemy się z Tobą w ciągu 2 godzin.'
+4 -2
View File
@@ -9,6 +9,8 @@ import { MobileMenu } from "./MobileMenu";
import { useCartStore } from "@/lib/cart-store"; import { useCartStore } from "@/lib/cart-store";
import { companyDetails } from "@/content/company"; import { companyDetails } from "@/content/company";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { buttonClasses } from '@/components/ui/Button';
export function Header() { export function Header() {
const [isScrolled, setIsScrolled] = useState(false); const [isScrolled, setIsScrolled] = useState(false);
@@ -240,13 +242,13 @@ export function Header() {
{/* CTA Button */} {/* CTA Button */}
<div className="hidden lg:flex items-center gap-3"> <div className="hidden lg:flex items-center gap-3">
<Link href="/zgloszenie-awarii" className="flex items-center gap-1.5 px-4 py-2 bg-red-500 text-white rounded-[var(--radius-field)] font-bold text-sm hover:bg-red-600 transition-colors whitespace-nowrap"> <Link href="/zgloszenie-awarii" className={buttonClasses({ variant: 'error', size: 'sm' })}>
<Wrench className="size-4" /> <Wrench className="size-4" />
Zgłoś awarię Zgłoś awarię
</Link> </Link>
<Link href="/kontakt" className="btn btn-primary font-bold"> <Link href="/kontakt" className={buttonClasses({ variant: 'primary', size: 'sm' })}>
Darmowa wycena Darmowa wycena
+2 -2
View File
@@ -50,7 +50,7 @@ export const ConfiguratorTeaser = () => {
<Icon className="w-5 h-5" /> <Icon className="w-5 h-5" />
</div> </div>
<div className="w-[calc(100%-4rem)] md:w-[calc(50%-3rem)] bg-white/10 border border-white/20 p-4 rounded-xl backdrop-blur-sm group-hover:bg-white/20 transition-colors"> <div className="w-[calc(100%-4rem)] md:w-[calc(50%-3rem)] bg-white/10 border border-white/20 p-4 rounded-xl backdrop-blur-sm group-hover:bg-white/20 transition-colors">
<h4 className="font-semibold text-lg">{step.label}</h4> <h3 className="font-semibold text-lg">{step.label}</h3>
<p className="text-sm text-gray-300">Krok {idx + 1}</p> <p className="text-sm text-gray-300">Krok {idx + 1}</p>
</div> </div>
</div> </div>
@@ -62,7 +62,7 @@ export const ConfiguratorTeaser = () => {
<div className="mt-8 bg-accent/20 border border-accent/40 rounded-xl p-4 flex items-start"> <div className="mt-8 bg-accent/20 border border-accent/40 rounded-xl p-4 flex items-start">
<Lightbulb className="w-6 h-6 text-accent shrink-0 mr-3 mt-0.5" /> <Lightbulb className="w-6 h-6 text-accent shrink-0 mr-3 mt-0.5" />
<div> <div>
<h5 className="font-semibold text-accent-light mb-1">Porada eksperta</h5> <h4 className="font-semibold text-accent-light mb-1">Porada eksperta</h4>
<p className="text-sm text-gray-200"> <p className="text-sm text-gray-200">
Szybki przelicznik mocy: <strong>10 m² = 1 kW</strong> mocy chłodniczej. Dla pokoju 25 m² szukaj urządzenia o mocy ok. 2.5 kW. Szybki przelicznik mocy: <strong>10 m² = 1 kW</strong> mocy chłodniczej. Dla pokoju 25 m² szukaj urządzenia o mocy ok. 2.5 kW.
</p> </p>
+1 -1
View File
@@ -55,7 +55,7 @@ export const FundingSection = () => {
<div className="flex justify-between items-start mb-8"> <div className="flex justify-between items-start mb-8">
<div> <div>
<p className="text-sm text-gray-500 font-semibold mb-1">Twój kosztorys z dotacją</p> <p className="text-sm text-gray-500 font-semibold mb-1">Twój kosztorys z dotacją</p>
<h4 className="text-xl font-bold text-primary">Przykładowa kalkulacja</h4> <h3 className="text-xl font-bold text-primary">Przykładowa kalkulacja</h3>
</div> </div>
<div className="w-12 h-12 bg-accent/10 rounded-full flex items-center justify-center"> <div className="w-12 h-12 bg-accent/10 rounded-full flex items-center justify-center">
<FileText className="w-6 h-6 text-accent" /> <FileText className="w-6 h-6 text-accent" />
+2 -2
View File
@@ -66,10 +66,10 @@ export const PricingTable = () => {
<div className="flex flex-col md:flex-row gap-8 items-start justify-between bg-gray-50 p-6 rounded-xl border border-gray-100"> <div className="flex flex-col md:flex-row gap-8 items-start justify-between bg-gray-50 p-6 rounded-xl border border-gray-100">
<div className="flex-1"> <div className="flex-1">
<h4 className="font-semibold text-primary mb-3 flex items-center gap-2"> <h3 className="font-semibold text-primary mb-3 flex items-center gap-2">
<Check className="w-5 h-5 text-accent" /> <Check className="w-5 h-5 text-accent" />
Co obejmuje montaż podstawowy? Co obejmuje montaż podstawowy?
</h4> </h3>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm text-gray-600"> <ul className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm text-gray-600">
<li className="flex items-start gap-2"><div className="w-1.5 h-1.5 rounded-full bg-accent mt-1.5 shrink-0" /> Wykonanie przewiertu przez ścianę</li> <li className="flex items-start gap-2"><div className="w-1.5 h-1.5 rounded-full bg-accent mt-1.5 shrink-0" /> Wykonanie przewiertu przez ścianę</li>
<li className="flex items-start gap-2"><div className="w-1.5 h-1.5 rounded-full bg-accent mt-1.5 shrink-0" /> Instalacja chłodnicza do 3 mb</li> <li className="flex items-start gap-2"><div className="w-1.5 h-1.5 rounded-full bg-accent mt-1.5 shrink-0" /> Instalacja chłodnicza do 3 mb</li>
+1 -1
View File
@@ -361,7 +361,7 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
<div className="bg-white rounded-2xl border border-border p-4"> <div className="bg-white rounded-2xl border border-border p-4">
<div className="flex items-center gap-2 mb-4"> <div className="flex items-center gap-2 mb-4">
<Zap className="size-4 text-accent" /> <Zap className="size-4 text-accent" />
<h3 className="text-sm font-bold text-primary font-heading">Kalkulator kosztów energii</h3> <h2 className="text-sm font-bold text-primary font-heading">Kalkulator kosztów energii</h2>
<div className="group relative ml-auto"> <div className="group relative ml-auto">
<Info className="size-4 text-text-muted cursor-help" /> <Info className="size-4 text-text-muted cursor-help" />
<div className="absolute right-0 bottom-6 w-56 bg-primary text-white text-xs rounded-lg p-2.5 hidden group-hover:block z-10"> <div className="absolute right-0 bottom-6 w-56 bg-primary text-white text-xs rounded-lg p-2.5 hidden group-hover:block z-10">
+54
View File
@@ -0,0 +1,54 @@
import React from 'react';
import { cn } from '@/lib/utils';
export type ButtonVariant = 'primary' | 'outline' | 'error';
export type ButtonSize = 'sm' | 'md' | 'lg';
export interface ButtonClassesProps {
variant?: ButtonVariant;
size?: ButtonSize;
className?: string;
}
export function buttonClasses({ variant = 'primary', size = 'md', className }: ButtonClassesProps = {}) {
const baseClasses = 'inline-flex items-center justify-center gap-2 whitespace-nowrap transition-colors';
const variantClasses = {
primary: 'btn btn-primary text-white font-bold',
outline: 'btn bg-white/10 text-white border border-white/20 hover:bg-white/20 font-bold',
error: 'btn btn-error text-white font-bold',
};
const sizeClasses = {
sm: 'btn-sm text-sm',
md: '', // default DaisyUI btn size
lg: 'btn-lg text-lg',
};
return cn(
baseClasses,
variantClasses[variant],
sizeClasses[size],
className
);
}
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, ButtonClassesProps {
children: React.ReactNode;
}
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, children, ...props }, ref) => {
return (
<button
ref={ref}
className={buttonClasses({ variant, size, className })}
{...props}
>
{children}
</button>
);
}
);
Button.displayName = 'Button';
+43
View File
@@ -0,0 +1,43 @@
import os
import re
from collections import Counter
dirs_to_search = ['app', 'components']
button_classes = []
class_regex = re.compile(r'className=["\']([^"\']+)["\']')
dynamic_class_regex = re.compile(r'className=\{`([^`]+)`\}')
for d in dirs_to_search:
for root, _, files in os.walk(d):
for file in files:
if file.endswith(('.tsx', '.jsx', '.ts', '.js')):
filepath = os.path.join(root, file)
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Find all classNames
matches = class_regex.findall(content) + dynamic_class_regex.findall(content)
for m in matches:
# Check if it looks like a button
if 'btn' in m or ('px-' in m and 'py-' in m and 'rounded' in m):
# Normalize spacing
normalized = ' '.join(m.split())
button_classes.append((normalized, filepath))
# Count frequencies
counts = Counter([c[0] for c in button_classes])
most_common = counts.most_common(10)
print("Top variants:")
for variant, count in most_common:
print(f"\nVariant ({count} times): {variant}")
# Find up to 3 files where it appears
files_seen = set()
for c, fpath in button_classes:
if c == variant and fpath not in files_seen:
files_seen.add(fpath)
print(f" - {fpath}")
if len(files_seen) >= 3:
break
+133
View File
@@ -0,0 +1,133 @@
const fs = require('fs');
const path = require('path');
const directories = ['app', 'components'];
const patterns = [
{
regex: /className=["']flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent\/90 transition-colors["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-2 px-6 py-3 bg-white\/10 text-white rounded-xl font-bold hover:bg-white\/20 transition-colors border border-white\/20["']/g,
replace: "className={buttonClasses({ variant: 'outline', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent\/90 transition-colors["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'lg' })}"
},
{
regex: /className=["']flex items-center gap-2 px-8 py-4 bg-white\/10 text-white rounded-xl font-bold text-lg hover:bg-white\/20 transition-colors border border-white\/20["']/g,
replace: "className={buttonClasses({ variant: 'outline', size: 'lg' })}"
},
{
regex: /className=["']btn btn-primary text-white font-bold["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']btn btn-primary font-bold["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-1\.5 px-4 py-2 bg-red-500 text-white rounded-\[var\(--radius-field\)\] font-bold text-sm hover:bg-red-600 transition-colors whitespace-nowrap["']/g,
replace: "className={buttonClasses({ variant: 'error', size: 'sm' })}"
}
];
// In case there are some dynamic classNames (template literals):
const dynamicPatterns = [
{
regex: /className=\{`flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent\/90 transition-colors (.*?)`\}/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md', className: `$1` })}"
},
{
regex: /className=\{`btn btn-primary font-bold (.*?)`\}/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md', className: `$1` })}"
}
];
function processDirectory(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const fullPath = path.join(dir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
processDirectory(fullPath);
} else if (file.endsWith('.tsx') || file.endsWith('.jsx')) {
// Don't process the Button.tsx itself
if (fullPath.includes('Button.tsx')) continue;
let content = fs.readFileSync(fullPath, 'utf8');
let originalContent = content;
let changed = false;
let usedButtonClasses = false;
let usedButtonComponent = false;
// 1. Tag conversion: <button className={...} ...> to <Button ...>
// We'll first apply the className replacements
for (const p of patterns) {
if (p.regex.test(content)) {
content = content.replace(p.regex, p.replace);
changed = true;
usedButtonClasses = true;
}
}
for (const p of dynamicPatterns) {
if (p.regex.test(content)) {
content = content.replace(p.regex, p.replace);
changed = true;
usedButtonClasses = true;
}
}
// 2. Convert `<button className={buttonClasses({ variant: 'X', size: 'Y' })}>` to `<Button variant="X" size="Y">`
// This is a bit tricky with regex, but let's try safely:
// Pattern: <button (.*?)className=\{buttonClasses\(\{ variant: '([^']+)', size: '([^']+)' \}\)\}(.*?)>
const buttonToComponentRegex = /<button([^>]*)className=\{buttonClasses\(\{\s*variant:\s*'([^']+)',\s*size:\s*'([^']+)'\s*\}\)\}([^>]*)>/g;
if (buttonToComponentRegex.test(content)) {
content = content.replace(buttonToComponentRegex, '<Button$1variant="$2" size="$3"$4>');
usedButtonComponent = true;
}
// Also match closing tags
if (usedButtonComponent) {
content = content.replace(/<\/button>/g, '</Button>');
}
if (changed) {
// We still might have used buttonClasses for <Link> tags
const needsButtonClasses = content.includes('buttonClasses(');
// Inject imports
const imports = [];
if (needsButtonClasses) imports.push('buttonClasses');
if (usedButtonComponent) imports.push('Button');
if (imports.length > 0) {
const importStr = `import { ${imports.join(', ')} } from '@/components/ui/Button';\n`;
// Find the last import
const importRegex = /^import.*$/gm;
let match;
let lastImportIndex = -1;
while ((match = importRegex.exec(content)) !== null) {
lastImportIndex = match.index + match[0].length;
}
if (lastImportIndex !== -1) {
content = content.slice(0, lastImportIndex) + '\n' + importStr + content.slice(lastImportIndex);
} else {
content = importStr + content;
}
}
fs.writeFileSync(fullPath, content, 'utf8');
console.log(`Updated ${fullPath}`);
}
}
}
}
for (const dir of directories) {
processDirectory(path.join(__dirname, dir));
}