Initial commit: New industrial design with green theme
This commit is contained in:
33
src/components/layout/FloatingContact.tsx
Normal file
33
src/components/layout/FloatingContact.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
'use client';
|
||||
|
||||
import { siteConfig } from '@/data/site-config';
|
||||
|
||||
export default function FloatingContact() {
|
||||
return (
|
||||
<div className="fixed bottom-6 right-6 z-40 flex flex-col gap-3">
|
||||
{/* LINE */}
|
||||
<a
|
||||
href={`https://line.me/ti/p/${siteConfig.lineId}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-14 h-14 bg-[#00B900] rounded-full flex items-center justify-center shadow-lg hover:scale-110 transition-transform"
|
||||
aria-label="ติดต่อผ่าน LINE"
|
||||
>
|
||||
<svg className="w-7 h-7 text-white" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
{/* Phone */}
|
||||
<a
|
||||
href={`tel:${siteConfig.phone}`}
|
||||
className="w-14 h-14 bg-primary-600 rounded-full flex items-center justify-center shadow-lg hover:scale-110 transition-transform"
|
||||
aria-label="โทรหาเรา"
|
||||
>
|
||||
<svg className="w-7 h-7 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
119
src/components/layout/Footer.tsx
Normal file
119
src/components/layout/Footer.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
import Link from 'next/link';
|
||||
import { siteConfig, workHours, mainNavigation } from '@/data/site-config';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-secondary-900 text-white">
|
||||
{/* Main Footer */}
|
||||
<div className="container mx-auto px-4 py-12">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{/* Company Info */}
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 bg-primary-600 rounded-lg flex items-center justify-center">
|
||||
<span className="text-white font-bold text-xl">D</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-bold text-lg">{siteConfig.name}</span>
|
||||
<span className="block text-primary-400 text-xs">{siteConfig.nameTh}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-secondary-300 text-sm mb-4">
|
||||
{siteConfig.description}
|
||||
</p>
|
||||
<div className="flex gap-3">
|
||||
<a
|
||||
href={siteConfig.facebookUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-10 h-10 bg-secondary-800 rounded-lg flex items-center justify-center hover:bg-primary-600 transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href={`https://line.me/ti/p/${siteConfig.lineId}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-10 h-10 bg-secondary-800 rounded-lg flex items-center justify-center hover:bg-primary-600 transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4 text-primary-400">ลิงก์ด่วน</h3>
|
||||
<ul className="space-y-2">
|
||||
{mainNavigation.slice(0, 5).map((item) => (
|
||||
<li key={item.href}>
|
||||
<Link href={item.href} className="text-secondary-300 hover:text-white transition-colors">
|
||||
{item.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Contact Info */}
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4 text-primary-400">ติดต่อเรา</h3>
|
||||
<ul className="space-y-3">
|
||||
<li className="flex items-start gap-3">
|
||||
<svg className="w-5 h-5 text-primary-500 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
<span className="text-secondary-300 text-sm">{siteConfig.address}</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-3">
|
||||
<svg className="w-5 h-5 text-primary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
<a href={`tel:${siteConfig.phone}`} className="text-secondary-300 hover:text-white text-sm">
|
||||
{siteConfig.phone}
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center gap-3">
|
||||
<svg className="w-5 h-5 text-primary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<a href={`mailto:${siteConfig.email}`} className="text-secondary-300 hover:text-white text-sm">
|
||||
{siteConfig.email}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Business Hours */}
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4 text-primary-400">เวลาทำการ</h3>
|
||||
<ul className="space-y-2">
|
||||
{workHours.map((item) => (
|
||||
<li key={item.day} className="flex justify-between text-sm">
|
||||
<span className="text-secondary-300">{item.day}</span>
|
||||
<span className={item.isClosed ? 'text-red-400' : 'text-white'}>
|
||||
{item.hours}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className="border-t border-secondary-800">
|
||||
<div className="container mx-auto px-4 py-4">
|
||||
<p className="text-center text-secondary-400 text-sm">
|
||||
© {new Date().getFullYear()} {siteConfig.name}. สงวนลิขสิทธิ์.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
157
src/components/layout/Header.tsx
Normal file
157
src/components/layout/Header.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { siteConfig, mainNavigation } from '@/data/site-config';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export default function Header() {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [activeDropdown, setActiveDropdown] = useState<string | null>(null);
|
||||
|
||||
return (
|
||||
<header className="fixed top-0 left-0 right-0 z-50 bg-secondary-900 shadow-industrial">
|
||||
{/* Top Bar */}
|
||||
<div className="bg-primary-600 py-2">
|
||||
<div className="container mx-auto px-4 flex justify-between items-center text-sm">
|
||||
<div className="flex items-center gap-6 text-white">
|
||||
<a href={`tel:${siteConfig.phone}`} className="flex items-center gap-2 hover:text-primary-100">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
{siteConfig.phone}
|
||||
</a>
|
||||
<a href={`mailto:${siteConfig.email}`} className="flex items-center gap-2 hover:text-primary-100">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
{siteConfig.email}
|
||||
</a>
|
||||
</div>
|
||||
<div className="hidden md:flex items-center gap-4">
|
||||
<a href={`https://line.me/ti/p/${siteConfig.lineId}`} className="flex items-center gap-1 text-white hover:text-primary-100">
|
||||
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"/>
|
||||
</svg>
|
||||
LINE
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Navigation */}
|
||||
<nav className="container mx-auto px-4">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-primary-600 rounded-lg flex items-center justify-center">
|
||||
<span className="text-white font-bold text-xl">D</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-white font-bold text-lg">{siteConfig.name}</span>
|
||||
<span className="block text-primary-400 text-xs">{siteConfig.nameTh}</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden lg:flex items-center gap-1">
|
||||
{mainNavigation.map((item) => (
|
||||
<div
|
||||
key={item.href}
|
||||
className="relative"
|
||||
onMouseEnter={() => item.children && setActiveDropdown(item.href)}
|
||||
onMouseLeave={() => setActiveDropdown(null)}
|
||||
>
|
||||
<Link
|
||||
href={item.href}
|
||||
className={cn(
|
||||
"px-4 py-2 text-white font-medium hover:text-primary-400 transition-colors flex items-center gap-1",
|
||||
item.children && "pr-2"
|
||||
)}
|
||||
>
|
||||
{item.label}
|
||||
{item.children && (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
)}
|
||||
</Link>
|
||||
|
||||
{/* Dropdown */}
|
||||
{item.children && activeDropdown === item.href && (
|
||||
<div className="absolute top-full left-0 w-64 bg-white shadow-industrial rounded-lg py-2 mt-1">
|
||||
{item.children.map((child) => (
|
||||
<div key={child.href} className="relative group">
|
||||
<Link
|
||||
href={child.href}
|
||||
className="block px-4 py-2 text-secondary-700 hover:bg-primary-50 hover:text-primary-700 transition-colors"
|
||||
>
|
||||
{child.label}
|
||||
</Link>
|
||||
{child.children && (
|
||||
<div className="hidden group-hover:block absolute left-full top-0 w-56 bg-white shadow-industrial rounded-lg py-2">
|
||||
{child.children.map((subChild) => (
|
||||
<Link
|
||||
key={subChild.href}
|
||||
href={subChild.href}
|
||||
className="block px-4 py-2 text-secondary-700 hover:bg-primary-50 hover:text-primary-700"
|
||||
>
|
||||
{subChild.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<Link href="/contact-us" className="btn-primary ml-4">
|
||||
ติดต่อเรา
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
className="lg:hidden text-white p-2"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
{mobileMenuOpen ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{mobileMenuOpen && (
|
||||
<div className="lg:hidden py-4 border-t border-secondary-700">
|
||||
{mainNavigation.map((item) => (
|
||||
<div key={item.href}>
|
||||
<Link
|
||||
href={item.href}
|
||||
className="block px-4 py-2 text-white hover:text-primary-400"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
<Link
|
||||
href="/contact-us"
|
||||
className="block mx-4 mt-4 btn-primary text-center"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
ติดต่อเรา
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user