♻️ Restructure: Move Astro to repository root

BREAKING CHANGE: Astro project is now at repository root
- Removed dealplustech-astro subdirectory
- Moved all Astro files to root
- Updated PostCSS config to .cjs
- Removed old Next.js files

 11 pages built successfully
 Cookie consent banner included
 Privacy/Terms links in footer
 Ready for Easypanel deployment (no root dir needed)

Migration path:
- Old structure: /dealplustech-astro/
- New structure: / (root)
This commit is contained in:
Kunthawat Greethong
2026-03-09 22:00:05 +07:00
parent 5b041a6a44
commit 7a67f68d9f
16524 changed files with 4277 additions and 1983574 deletions

View File

@@ -1,77 +0,0 @@
# APP ROUTER - Pages & Routing
**Generated:** 2026-03-08
## OVERVIEW
Next.js 14 App Router with Thai-language URLs, catch-all routing for products/portfolio, and SEO-heavy pages.
## STRUCTURE
```
src/app/
├── layout.tsx # Root layout (Kanit font, metadata, schema.org)
├── page.tsx # Homepage (hero, featured products)
├── [...slug]/page.tsx # Catch-all: products + portfolio (599 lines)
├── product/page.tsx # Product listing page
├── blog/ # WordPress integration
│ ├── page.tsx # Blog index
│ └── [slug]/page.tsx # Individual posts
├── about-us/page.tsx # Company info
├── services/page.tsx # Services overview
├── portfolio/page.tsx # Portfolio index
├── contact-us/page.tsx # Contact form
├── join-us/page.tsx # Careers
├── sales-engineer/page.tsx # Position-specific
├── all-projects/page.tsx # FAQ page
├── pipe/page.tsx # Category-specific
└── sitemap.ts # Dynamic sitemap generation
```
## WHERE TO LOOK
| Task | Location | Notes |
|------|----------|-------|
| Add new page | `src/app/{route}/page.tsx` | App Router conventions |
| Thai URL routing | `src/app/[...slug]/page.tsx` | Decodes URL-encoded slugs |
| SEO metadata | `src/app/layout.tsx` + individual pages | Schema.org structured data |
| Dynamic routes | `generateStaticParams()` | In catch-all page.tsx |
| 404 handling | `src/app/not-found.tsx` | Custom error page |
## CONVENTIONS
**Thai URLs**: Catch-all route handles `/ท่อพีพีอาร์ตราช้าง/` via `generateStaticParams()`.
**Page structure**:
```typescript
import Image from 'next/image'
import Link from 'next/link'
import { productCategories } from '@/data/site-config'
export default function Page() {
return (
<>
{/* Hero section */}
{/* Content sections */}
</>
)
}
```
**SEO content**: Product pages include `seoContent` from `productCategories` with structured data.
**Static generation**: All routes pre-built via `generateStaticParams()` in `[...slug]/page.tsx`.
## ANTI-PATTERNS (THIS PROJECT)
- **DO NOT** use `output: 'standalone'` in dev mode (breaks HMR) - configured in next.config.mjs with NODE_ENV guard
- **DO NOT** hardcode Thai slugs - use `product.href` from site-config
- **DO NOT** skip `decodeURIComponent()` for slug params - Thai URLs are URL-encoded
- **DO NOT** import entire `site-config.ts` in client components - it's 149KB
## NOTES
- **No middleware**: Thai routing handled via catch-all route, not middleware.ts
- **Blog**: Headless WordPress via `NEXT_PUBLIC_WORDPRESS_API_URL`
- **Sitemap**: Auto-generated in `sitemap.ts` from product categories + portfolio
- **Font**: Kanit (Thai Google Font) loaded in root layout

View File

@@ -1,599 +0,0 @@
import { notFound } from 'next/navigation';
import Image from 'next/image';
import Link from 'next/link';
import { productCategories, portfolioProjects } from '@/data/site-config';
import type { ProductCategory, FAQItem } from '@/types';
interface Props {
params: { slug: string[] };
}
// Generate all possible paths from product categories and portfolio projects
export async function generateStaticParams() {
const paths: { slug: string[] }[] = [];
// Add product category paths
productCategories.forEach((product) => {
// Remove leading slash and split the href
const pathParts = product.href.replace(/^\//, '').replace(/\/$/, '').split('/');
paths.push({ slug: pathParts });
});
// Add portfolio project paths
portfolioProjects.forEach((project) => {
const pathParts = project.href.replace(/^\//, '').replace(/\/$/, '').split('/');
paths.push({ slug: pathParts });
});
return paths;
}
type ContentType = 'product' | 'portfolio';
function findContentBySlug(slug: string[]): { type: ContentType; data: ProductCategory | typeof portfolioProjects[0] } | null {
// Decode URL-encoded slug parts
const decodedSlug = slug.map(part => decodeURIComponent(part));
const fullPath = '/' + decodedSlug.join('/') + '/';
// Check products first
const product = productCategories.find((p) => p.href === fullPath);
if (product) {
return { type: 'product', data: product };
}
// Check portfolio projects
const portfolio = portfolioProjects.find((p) => p.href === fullPath);
if (portfolio) {
return { type: 'portfolio', data: portfolio };
}
return null;
}
export async function generateMetadata({ params }: Props) {
const content = findContentBySlug(params.slug);
if (!content) {
return { title: 'ไม่พบหน้า' };
}
const { type, data } = content;
if (type === 'product') {
const product = data as ProductCategory;
const title = product.keywords?.[0]
? `${product.name} | ${product.keywords[0]} - ดีลพลัสเทค`
: `${product.name} - ${product.nameEn} | ดีลพลัสเทค`;
return {
title,
description: product.description,
keywords: product.keywords?.join(', '),
alternates: {
canonical: product.href,
},
openGraph: {
title: product.name,
description: product.description,
images: [product.image],
type: 'website',
url: `https://dealplustech.co.th${product.href}`,
},
};
}
return {
title: data.name,
description: data.description,
};
}
// Schema.org JSON-LD for Products
function ProductSchema({ product }: { product: ProductCategory }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.image,
brand: {
'@type': 'Brand',
name: product.schemaData?.brand || product.nameEn,
},
manufacturer: {
'@type': 'Organization',
name: product.schemaData?.manufacturer || 'ดีลพลัสเทค',
},
...(product.schemaData?.sku && { sku: product.schemaData.sku }),
...(product.schemaData?.mpn && { mpn: product.schemaData.mpn }),
...(product.schemaData?.material && { material: product.schemaData.material }),
category: product.schemaData?.category || 'Industrial Pipe & Equipment',
offers: {
'@type': 'Offer',
availability: 'https://schema.org/InStock',
priceCurrency: 'THB',
seller: {
'@type': 'Organization',
name: 'ดีลพลัสเทค',
},
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// BreadcrumbList Schema for SEO
function BreadcrumbSchema({ product }: { product: ProductCategory }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{
'@type': 'ListItem',
position: 1,
name: 'หน้าแรก',
item: 'https://dealplustech.co.th',
},
{
'@type': 'ListItem',
position: 2,
name: 'สินค้า',
item: 'https://dealplustech.co.th/product/',
},
{
'@type': 'ListItem',
position: 3,
name: product.name,
item: `https://dealplustech.co.th${product.href}`,
},
],
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// FAQ Schema for SEO
function FAQSchema({ faq }: { faq: FAQItem[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faq.map((item) => ({
'@type': 'Question',
name: item.question,
acceptedAnswer: {
'@type': 'Answer',
text: item.answer,
},
})),
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
export default function DynamicPage({ params }: Props) {
const content = findContentBySlug(params.slug);
if (!content) {
notFound();
}
const { type, data } = content;
// Render portfolio project page
if (type === 'portfolio') {
return <PortfolioPage project={data as typeof portfolioProjects[0]} />;
}
// Render product page
return <ProductPage product={data as ProductCategory} />;
}
// Product Page Component
function ProductPage({ product }: { product: ProductCategory }) {
// Find related products - either by explicit IDs or same category
const relatedProducts = product.relatedProductIds
? productCategories.filter((p) => product.relatedProductIds?.includes(p.id))
: productCategories
.filter((p) => p.slug === product.slug && p.id !== product.id)
.slice(0, 4);
return (
<>
{/* Schema.org Structured Data */}
<ProductSchema product={product} />
<BreadcrumbSchema product={product} />
{product.faq && product.faq.length > 0 && <FAQSchema faq={product.faq} />}
<div className="pt-24 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm flex-wrap">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li>
<Link href="/product" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium">{product.name}</li>
</ol>
</nav>
{/* Product Header */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 mb-12">
{/* Product Image */}
<div className="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<Image
src={product.image}
alt={`${product.name} - ${product.nameEn}`}
fill
className="object-cover"
priority
/>
</div>
{/* Product Info */}
<div>
<span className="text-primary-600 font-semibold">{product.nameEn}</span>
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mt-2 mb-4">
{product.name}
</h1>
<p className="text-secondary-600 text-lg mb-6 leading-relaxed">
{product.description}
</p>
{/* CTA */}
<div className="flex flex-wrap gap-4 mb-6">
<Link href="/contact-us" className="btn-primary">
</Link>
<a
href="tel:090-555-1415"
className="btn-outline"
>
โทรสอบถาม: 090-555-1415
</a>
</div>
{/* Quick Contact Info */}
<div className="bg-secondary-50 rounded-lg p-4 space-y-2">
<div className="flex items-center gap-2 text-secondary-600">
<svg className="w-5 h-5 text-primary-600" 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>
<span>: <strong>090-555-1415</strong></span>
</div>
<div className="flex items-center gap-2 text-secondary-600">
<svg className="w-5 h-5 text-primary-600" 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>
<span>Email: <strong>info@dealplustech.co.th</strong></span>
</div>
<div className="flex items-center gap-2 text-secondary-600">
<svg className="w-5 h-5 text-primary-600" fill="currentColor" viewBox="0 0 24 24">
<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>
<span>LINE: <strong>@dealplustech</strong></span>
</div>
</div>
</div>
</div>
{/* Specifications Section */}
{product.specifications && product.specifications.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</h2>
<div className="bg-white rounded-xl border border-secondary-200 overflow-hidden">
<table className="w-full">
<tbody>
{product.specifications.map((spec, index) => (
<tr key={index} className={index % 2 === 0 ? 'bg-secondary-50' : 'bg-white'}>
<td className="px-6 py-4 font-medium text-secondary-700 w-1/3">{spec.label}</td>
<td className="px-6 py-4 text-secondary-900">
{spec.value}{spec.unit ? ` ${spec.unit}` : ''}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
)}
{/* Product Tables Section */}
{product.productTables && product.productTables.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
</h2>
<div className="space-y-8">
{product.productTables.map((table, tableIndex) => (
<div key={tableIndex} className="bg-white rounded-xl border border-secondary-200 overflow-hidden">
<h3 className="text-lg font-semibold text-secondary-800 p-4 bg-secondary-50 border-b border-secondary-200">
{table.tableName}
</h3>
<div className="overflow-x-auto">
<table className="w-full min-w-[600px]">
<thead>
<tr className="bg-primary-50">
{table.headers.map((header, headerIndex) => (
<th key={headerIndex} className="px-4 py-3 text-left text-sm font-semibold text-primary-700">
{header}
</th>
))}
</tr>
</thead>
<tbody>
{table.rows.map((row, rowIndex) => (
<tr key={rowIndex} className={rowIndex % 2 === 0 ? 'bg-white' : 'bg-secondary-50'}>
{row.map((cell, cellIndex) => (
<td key={cellIndex} className="px-4 py-3 text-sm text-secondary-700">
{cell}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
</div>
))}
</div>
</section>
)}
{/* Features Section */}
{product.features && product.features.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{product.features.map((feature, index) => (
<div key={index} className="flex items-start gap-3 p-4 bg-primary-50 rounded-lg">
<svg className="w-5 h-5 text-primary-600 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span className="text-secondary-700">{feature}</span>
</div>
))}
</div>
</section>
)}
{/* Applications Section */}
{product.applications && product.applications.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</h2>
<div className="flex flex-wrap gap-3">
{product.applications.map((app, index) => (
<span key={index} className="inline-flex items-center px-4 py-2 bg-secondary-100 text-secondary-700 rounded-full font-medium">
{app}
</span>
))}
</div>
</section>
)}
{/* Certifications Section */}
{product.certifications && product.certifications.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
</h2>
<div className="flex flex-wrap gap-3">
{product.certifications.map((cert, index) => (
<span key={index} className="inline-flex items-center px-4 py-2 bg-primary-100 text-primary-700 rounded-lg font-semibold">
{cert}
</span>
))}
</div>
</section>
)}
{/* SEO Content Section */}
{product.seoContent && (
<section className="mb-12">
<div className="prose prose-lg max-w-none">
<div dangerouslySetInnerHTML={{ __html: product.seoContent.replace(/\n/g, '<br/>') }} />
</div>
</section>
)}
{/* FAQ Section */}
{product.faq && product.faq.length > 0 && (
<section className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 flex items-center gap-2">
<svg className="w-6 h-6 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</h2>
<div className="space-y-4">
{product.faq.map((item, index) => (
<details key={index} className="group bg-white rounded-lg border border-secondary-200 overflow-hidden">
<summary className="flex items-center justify-between p-5 cursor-pointer font-medium text-secondary-900 hover:bg-secondary-50">
<span>{item.question}</span>
<svg className="w-5 h-5 text-secondary-500 group-open:rotate-180 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</summary>
<div className="px-5 pb-5 text-secondary-600 border-t border-secondary-100 pt-4">
{item.answer}
</div>
</details>
))}
</div>
</section>
)}
{/* Related Products */}
{relatedProducts.length > 0 && (
<section className="mt-16">
<h2 className="text-2xl font-bold text-secondary-900 mb-6">
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{relatedProducts.map((related) => (
<Link
key={related.id}
href={related.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={related.image}
alt={related.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-4">
<span className="text-xs text-primary-600 font-semibold">
{related.nameEn}
</span>
<h3 className="text-lg font-bold text-secondary-900 mt-1 group-hover:text-primary-600 transition-colors">
{related.name}
</h3>
</div>
</Link>
))}
</div>
</section>
)}
</div>
</div>
</>
);
}
// Portfolio Page Component
function PortfolioPage({ project }: { project: typeof portfolioProjects[0] }) {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li>
<Link href="/portfolio" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium">{project.name}</li>
</ol>
</nav>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
{/* Project Image */}
<div className="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<Image
src={project.image}
alt={project.name}
fill
className="object-cover"
priority
/>
</div>
{/* Project Info */}
<div>
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
{project.name}
</h1>
<p className="text-secondary-600 text-lg mb-6">
{project.description}
</p>
{/* CTA */}
<div className="flex flex-wrap gap-4">
<Link href="/contact-us" className="btn-primary">
</Link>
<Link href="/portfolio" className="btn-outline">
</Link>
</div>
</div>
</div>
{/* Other Projects */}
<div className="mt-16">
<h2 className="text-2xl font-bold text-secondary-900 mb-6">
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{portfolioProjects.filter(p => p.id !== project.id).slice(0, 4).map((other) => (
<Link
key={other.id}
href={other.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={other.image}
alt={other.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-4">
<h3 className="text-lg font-bold text-secondary-900 group-hover:text-primary-600 transition-colors">
{other.name}
</h3>
</div>
</Link>
))}
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,119 +0,0 @@
import Image from 'next/image';
import { siteConfig } from '@/data/site-config';
export const metadata = {
title: 'เกี่ยวกับเรา',
description: 'เรียนรู้เพิ่มเติมเกี่ยวกับดีลพลัสเทค ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ',
};
export default function AboutPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Hero */}
<div className="relative h-[400px] -mt-32 mb-12 rounded-b-3xl overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-800 to-secondary-900" />
<div className="absolute inset-0 flex items-center justify-center">
<div className="text-center">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
<span className="text-primary-400">{siteConfig.name}</span>
</h1>
<p className="text-xl text-secondary-200">
</p>
</div>
</div>
</div>
{/* Company Story */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 mb-16">
<div>
<h2 className="text-3xl font-bold text-secondary-900 mb-6"></h2>
<div className="space-y-4 text-secondary-600">
<p>
{siteConfig.nameTh}
</p>
<p>
10
</p>
<p>
</p>
</div>
</div>
<div className="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<Image
src="/images/2021/03/hdpe-pipe_000C.jpg"
alt="เกี่ยวกับดีลพลัสเทค"
fill
className="object-cover"
/>
</div>
</div>
{/* Vision & Mission */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16">
<div className="card-industrial">
<h3 className="text-2xl font-bold text-primary-400 mb-4"></h3>
<p className="text-secondary-200">
</p>
</div>
<div className="card-industrial">
<h3 className="text-2xl font-bold text-primary-400 mb-4"></h3>
<p className="text-secondary-200">
</p>
</div>
</div>
{/* Core Values */}
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-secondary-900 mb-8"></h2>
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="p-6 bg-primary-50 rounded-xl">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 className="font-bold text-secondary-900 mb-2"></h4>
<p className="text-secondary-600 text-sm"></p>
</div>
<div className="p-6 bg-primary-50 rounded-xl">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 className="font-bold text-secondary-900 mb-2"></h4>
<p className="text-secondary-600 text-sm"></p>
</div>
<div className="p-6 bg-primary-50 rounded-xl">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
</div>
<h4 className="font-bold text-secondary-900 mb-2"></h4>
<p className="text-secondary-600 text-sm"></p>
</div>
<div className="p-6 bg-primary-50 rounded-xl">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<h4 className="font-bold text-secondary-900 mb-2"></h4>
<p className="text-secondary-600 text-sm"></p>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,83 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
import { portfolioProjects } from '@/data/site-config';
export const metadata = {
title: 'ผลงานทั้งหมด | All Projects - ดีลพลัสเทค',
description: 'ผลงานการติดตั้งระบบท่อทุกโครงการ โครงการระบบท่อโรงงาน โครงการระบบน้ำ โครงการระบบดับเพลิง',
};
export default function AllProjectsPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium"></li>
</ol>
</nav>
{/* Header */}
<div className="mb-12">
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
</h1>
<p className="text-secondary-600 text-lg max-w-3xl">
</p>
</div>
{/* Projects Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{portfolioProjects.map((project) => (
<Link
key={project.id}
href={project.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={project.image}
alt={project.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-4">
<h2 className="text-lg font-bold text-secondary-900 group-hover:text-primary-600 transition-colors">
{project.name}
</h2>
<p className="text-sm text-secondary-600 mt-2 line-clamp-2">
{project.description}
</p>
</div>
</Link>
))}
</div>
{/* CTA */}
<div className="mt-12 text-center">
<p className="text-secondary-600 mb-4">
?
</p>
<div className="flex justify-center gap-4">
<Link href="/contact-us" className="btn-primary">
</Link>
<a href="tel:090-555-1415" className="btn-outline">
090-555-1415
</a>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,143 +0,0 @@
import { notFound } from 'next/navigation';
import Image from 'next/image';
import Link from 'next/link';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
import gfm from 'remark-gfm';
interface Props {
params: Promise<{ slug: string }>;
}
async function getPost(slug: string) {
const blogDir = path.join(process.cwd(), 'src/content/blog');
const filePath = path.join(blogDir, `${slug}.md`);
if (!fs.existsSync(filePath)) {
return null;
}
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data, content } = matter(fileContent);
const processedContent = await remark()
.use(gfm)
.use(html, { sanitize: false })
.process(content);
const contentHtml = processedContent.toString();
// Support both 'category' and 'categories' field names
const category = data.category || (Array.isArray(data.categories) ? data.categories[0] : 'ทั่วไป');
// Support both 'image' and 'featuredImage' field names
const image = data.image || data.featuredImage || '/images/2021/03/ppr-pipe_000C.jpg';
return {
slug,
title: data.title || 'ไม่มีชื่อ',
excerpt: data.excerpt || '',
date: data.date || new Date().toISOString(),
author: data.author || 'ดีลพลัสเทค',
category,
image,
content: contentHtml,
};
}
export async function generateMetadata({ params }: Props) {
const { slug } = await params;
const decodedSlug = decodeURIComponent(slug);
const post = await getPost(decodedSlug);
if (!post) return { title: 'ไม่พบบทความ' };
return {
title: post.title,
description: post.excerpt,
};
}
export async function generateStaticParams() {
const blogDir = path.join(process.cwd(), 'src/content/blog');
const files = fs.readdirSync(blogDir).filter(f => f.endsWith('.md'));
return files.map(filename => ({
slug: filename.replace('.md', ''),
}));
}
export default async function BlogPostPage({ params }: Props) {
const { slug } = await params;
const decodedSlug = decodeURIComponent(slug);
const post = await getPost(decodedSlug);
if (!post) {
notFound();
}
return (
<div className="pt-32 pb-16">
<article className="container mx-auto px-4">
{/* Header */}
<header className="max-w-3xl mx-auto mb-8">
<Link
href="/blog"
className="inline-flex items-center text-primary-600 hover:text-primary-700 mb-4"
>
<svg className="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</Link>
<span className="industrial-badge">{post.category}</span>
<h1 className="text-3xl md:text-4xl lg:text-5xl font-bold text-secondary-900 mt-4 mb-4">
{post.title}
</h1>
<div className="flex items-center gap-4 text-secondary-600">
<span>{post.author}</span>
<span></span>
<time>
{new Date(post.date).toLocaleDateString('th-TH', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</time>
</div>
</header>
{/* Featured Image */}
<div className="relative aspect-video max-w-4xl mx-auto rounded-xl overflow-hidden mb-8">
<Image
src={post.image}
alt={post.title}
fill
className="object-cover"
/>
</div>
{/* Content */}
<div
className="max-w-3xl mx-auto prose prose-lg prose-headings:font-bold prose-headings:text-secondary-900 prose-p:text-secondary-600 prose-a:text-primary-600 prose-strong:text-secondary-900"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
{/* CTA */}
<div className="max-w-3xl mx-auto mt-12 bg-secondary-800 rounded-2xl p-8 text-center">
<h2 className="text-2xl font-bold text-white mb-4">
?
</h2>
<p className="text-secondary-300 mb-6">
</p>
<Link href="/contact-us" className="btn-primary">
</Link>
</div>
</article>
</div>
);
}

View File

@@ -1,106 +0,0 @@
import Link from 'next/link';
import Image from 'next/image';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
export const metadata = {
title: 'บทความ',
description: 'บทความความรู้เกี่ยวกับวัสดุท่อ อุปกรณ์ระบบท่อ และเทคนิคการติดตั้ง',
};
function getBlogPosts() {
const blogDir = path.join(process.cwd(), 'src/content/blog');
const files = fs.readdirSync(blogDir).filter(f => f.endsWith('.md'));
return files.map(filename => {
const filePath = path.join(blogDir, filename);
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data } = matter(fileContent);
// Support both 'category' and 'categories' field names
const category = data.category || (Array.isArray(data.categories) ? data.categories[0] : 'ทั่วไป');
// Support both 'image' and 'featuredImage' field names
const image = data.image || data.featuredImage || '/images/2021/03/ppr-pipe_000C.jpg';
return {
slug: filename.replace('.md', ''),
title: data.title || 'ไม่มีชื่อ',
excerpt: data.excerpt || '',
date: data.date || new Date().toISOString(),
author: data.author || 'ดีลพลัสเทค',
category,
image,
};
}).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}
export default function BlogPage() {
const posts = getBlogPosts();
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Hero */}
<div className="text-center mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h1>
<p className="text-xl text-secondary-600 max-w-2xl mx-auto">
</p>
</div>
{/* Blog Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{posts.map((post) => (
<Link
key={post.slug}
href={`/blog/${post.slug}`}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={post.image}
alt={post.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute top-4 left-4">
<span className="industrial-badge">{post.category}</span>
</div>
</div>
<div className="p-6">
<time className="text-sm text-secondary-500">
{new Date(post.date).toLocaleDateString('th-TH', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</time>
<h3 className="text-xl font-bold text-secondary-900 mt-2 group-hover:text-primary-600 transition-colors">
{post.title}
</h3>
<p className="text-secondary-600 text-sm mt-2 line-clamp-2">
{post.excerpt}
</p>
<span className="text-primary-600 font-semibold flex items-center gap-2 mt-4">
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</span>
</div>
</Link>
))}
</div>
{posts.length === 0 && (
<div className="text-center py-12">
<p className="text-secondary-600"></p>
</div>
)}
</div>
</div>
);
}

View File

@@ -1,108 +0,0 @@
import { siteConfig, workHours } from '@/data/site-config';
export const metadata = {
title: 'ติดต่อเรา',
description: 'ติดต่อดีลพลัสเทค สอบถามข้อมูลสินค้า ขอใบเสนอราคา หรือติดต่อทีมงาน',
};
export default function ContactPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Hero */}
<div className="text-center mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h1>
<p className="text-xl text-secondary-600 max-w-2xl mx-auto">
</p>
</div>
<div className="max-w-2xl mx-auto">
{/* Contact Info */}
<div className="bg-secondary-800 rounded-2xl p-8 mb-8">
<h2 className="text-2xl font-bold text-white mb-6"></h2>
<div className="space-y-6">
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" 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>
</div>
<div>
<h3 className="font-bold text-white"></h3>
<p className="text-secondary-300">{siteConfig.address}</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 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>
</div>
<div>
<h3 className="font-bold text-white"></h3>
<a href={`tel:${siteConfig.phone}`} className="text-primary-400 hover:text-primary-300">
{siteConfig.phone}
</a>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" 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>
</div>
<div>
<h3 className="font-bold text-white"></h3>
<a href={`mailto:${siteConfig.email}`} className="text-primary-400 hover:text-primary-300">
{siteConfig.email}
</a>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-[#00B900] rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 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>
</div>
<div>
<h3 className="font-bold text-white">LINE Official</h3>
<a
href={`https://line.me/ti/p/${siteConfig.lineId}`}
target="_blank"
rel="noopener noreferrer"
className="text-primary-400 hover:text-primary-300"
>
{siteConfig.lineId}
</a>
</div>
</div>
</div>
</div>
{/* Business Hours */}
<div className="bg-primary-600 rounded-2xl p-8">
<h2 className="text-2xl font-bold text-white mb-6"></h2>
<ul className="space-y-3">
{workHours.map((item) => (
<li key={item.day} className="flex justify-between">
<span className="text-primary-100">{item.day}</span>
<span className={`font-semibold ${item.isClosed ? 'text-red-200' : 'text-white'}`}>
{item.hours}
</span>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,174 +0,0 @@
import Link from 'next/link';
export const metadata = {
title: 'ร่วมงานกับเรา | Join Us - ดีลพลัสเทค',
description: 'ร่วมงานกับดีลพลัสเทค เรามอบโอกาสทางอาชีพที่ดี สวัสดิการครบครัน ร่วมเติบโตไปกับเรา',
};
const jobPositions = [
{
id: 'sales-engineer',
title: 'Sales Engineer',
titleTh: 'วิศวกรฝ่ายขาย',
type: 'Full-time',
location: 'กรุงเทพมหานคร',
salary: 'เจรจาต่อรอง',
description: 'รับผิดชอบการขายและให้คำปรึกษาด้านเทคนิคสำหรับผลิตภัณฑ์ท่อและอุปกรณ์ระบบท่อ',
requirements: [
'ปริญญาตรี สาขาวิศวกรรมเครื่องกล วิศวกรรมโยธา หรือสาขาที่เกี่ยวข้อง',
'มีประสบการณ์อย่างน้อย 1-3 ปี ในตำแหน่ง Sales Engineer',
'มีความรู้ด้านท่อและอุปกรณ์ระบบท่อจะได้รับการพิจารณาเป็นพิเศษ',
'สามารถขับรถและมีใบขับขี่',
'มีทัศนคติดี กระตือรือร้น และสามารถทำงานเป็นทีมได้',
],
},
{
id: 'sales-representative',
title: 'Sales Representative',
titleTh: 'พนักงานขาย',
type: 'Full-time',
location: 'กรุงเทพมหานคร',
salary: 'เจรจาต่อรอง',
description: 'รับผิดชอบการขายผลิตภัณฑ์ท่อและอุปกรณ์ระบบท่อให้กับลูกค้าใหม่และลูกค้าเดิม',
requirements: [
'ปริญญาตรี สาขาใดก็ได้',
'มีประสบการณ์ด้านการขายอย่างน้อย 1 ปี',
'มีทักษะการสื่อสารที่ดี',
'สามารถขับรถและมีใบขับขี่',
'มีทัศนคติดี กระตือรือร้น',
],
},
];
export default function JoinUsPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium"></li>
</ol>
</nav>
{/* Header */}
<div className="mb-12 text-center">
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
</h1>
<p className="text-secondary-600 text-lg max-w-2xl mx-auto">
</p>
</div>
{/* Why Join Us */}
<div className="mb-12 bg-primary-50 rounded-xl p-8">
<h2 className="text-2xl font-bold text-secondary-900 mb-6 text-center">
?
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="text-center">
<div className="w-16 h-16 bg-primary-600 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h3 className="text-lg font-bold text-secondary-900 mb-2"></h3>
<p className="text-secondary-600"></p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-primary-600 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
</div>
<h3 className="text-lg font-bold text-secondary-900 mb-2"></h3>
<p className="text-secondary-600"> </p>
</div>
<div className="text-center">
<div className="w-16 h-16 bg-primary-600 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
</div>
<h3 className="text-lg font-bold text-secondary-900 mb-2"></h3>
<p className="text-secondary-600"></p>
</div>
</div>
</div>
{/* Open Positions */}
<div className="mb-12">
<h2 className="text-2xl font-bold text-secondary-900 mb-6">
</h2>
<div className="space-y-6">
{jobPositions.map((job) => (
<div key={job.id} className="bg-white rounded-xl p-6 shadow-card">
<div className="flex flex-col md:flex-row md:items-center md:justify-between mb-4">
<div>
<h3 className="text-xl font-bold text-secondary-900">
{job.title}
</h3>
<p className="text-primary-600">{job.titleTh}</p>
</div>
<div className="flex flex-wrap gap-2 mt-2 md:mt-0">
<span className="px-3 py-1 bg-secondary-100 text-secondary-700 rounded-full text-sm">
{job.type}
</span>
<span className="px-3 py-1 bg-secondary-100 text-secondary-700 rounded-full text-sm">
{job.location}
</span>
<span className="px-3 py-1 bg-primary-100 text-primary-700 rounded-full text-sm">
{job.salary}
</span>
</div>
</div>
<p className="text-secondary-600 mb-4">{job.description}</p>
<div className="mb-4">
<h4 className="font-semibold text-secondary-900 mb-2">:</h4>
<ul className="list-disc list-inside text-secondary-600 space-y-1">
{job.requirements.map((req, index) => (
<li key={index}>{req}</li>
))}
</ul>
</div>
<Link
href={`/sales-engineer`}
className="btn-primary inline-block"
>
</Link>
</div>
))}
</div>
</div>
{/* Contact */}
<div className="bg-secondary-100 rounded-xl p-8 text-center">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
?
</h2>
<p className="text-secondary-600 mb-6">
info@dealplustech.co.th
090-555-1415
</p>
<div className="flex justify-center gap-4">
<a href="mailto:info@dealplustech.co.th" className="btn-primary">
</a>
<Link href="/contact-us" className="btn-outline">
</Link>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,152 +0,0 @@
import type { Metadata } from 'next';
import { Kanit } from 'next/font/google';
import '@/styles/globals.css';
import Header from '@/components/layout/Header';
import Footer from '@/components/layout/Footer';
import FloatingContact from '@/components/layout/FloatingContact';
import GoogleAnalytics from '@/components/analytics/GoogleAnalytics';
const kanit = Kanit({
subsets: ['latin', 'thai'],
weight: ['300', '400', '500', '600', '700'],
variable: '--font-kanit',
display: 'swap',
});
export const metadata: Metadata = {
title: {
default: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ',
template: '%s | ดีลพลัสเทค',
},
description: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ ท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร',
keywords: ['ท่อพีพีอาร์', 'ท่อ HDPE', 'ท่อ PVC', 'วาล์ว', 'อุปกรณ์ท่อ', 'ดีลพลัสเทค'],
authors: [{ name: 'Deal Plus Tech' }],
metadataBase: new URL('https://dealplustech.co.th'),
alternates: {
canonical: '/',
},
openGraph: {
type: 'website',
locale: 'th_TH',
url: 'https://dealplustech.co.th',
siteName: 'ดีลพลัสเทค',
title: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ',
description: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ ท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร',
images: [
{
url: '/og-image.jpg',
width: 1200,
height: 630,
alt: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ',
},
],
},
twitter: {
card: 'summary_large_image',
site: '@dealplustech',
title: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ',
description: 'ดีลพลัสเทค - ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ ท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร',
images: ['/og-image.jpg'],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
};
// LocalBusiness Schema for SEO
function LocalBusinessSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'LocalBusiness',
'@id': 'https://dealplustech.co.th/#organization',
name: 'ดีลพลัสเทค',
alternateName: 'Deal Plus Tech Co., Ltd.',
description: 'ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ จำหน่ายท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร',
url: 'https://dealplustech.co.th',
logo: 'https://dealplustech.co.th/images/logo.png',
image: 'https://dealplustech.co.th/og-image.jpg',
telephone: '+66-90-555-1415',
email: 'info@dealplustech.co.th',
address: {
'@type': 'PostalAddress',
streetAddress: '9/70 ซอยนครลุง 17',
addressLocality: 'แขวงบางไผ่',
addressRegion: 'เขตบางแค',
addressCountry: 'TH',
postalCode: '10160',
},
geo: {
'@type': 'GeoCoordinates',
latitude: '13.7244',
longitude: '100.4044',
},
openingHoursSpecification: [
{
'@type': 'OpeningHoursSpecification',
dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
opens: '08:30',
closes: '17:30',
},
{
'@type': 'OpeningHoursSpecification',
dayOfWeek: 'Saturday',
opens: '08:30',
closes: '12:00',
},
],
priceRange: '$$',
sameAs: [
'https://facebook.com/dealplustech',
'https://line.me/ti/p/@dealplustech',
],
areaServed: {
'@type': 'Country',
name: 'Thailand',
},
knowsAbout: [
'ท่อพีพีอาร์ (PPR Pipe)',
'ท่อ HDPE',
'ท่อ PVC',
'วาล์ว (Valve)',
'อุปกรณ์ระบบท่อ',
'ระบบดับเพลิง',
'ระบบปรับอากาศ HVAC',
],
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="th" className={kanit.variable}>
<head>
<LocalBusinessSchema />
</head>
<body className="font-sans">
<GoogleAnalytics />
<Header />
<main className="min-h-screen">{children}</main>
<Footer />
<FloatingContact />
</body>
</html>
);
}

View File

@@ -1,20 +0,0 @@
import Link from 'next/link';
export default function NotFound() {
return (
<div className="min-h-[60vh] flex items-center justify-center">
<div className="text-center px-4">
<h1 className="text-6xl font-bold text-secondary-900 mb-4">404</h1>
<h2 className="text-2xl font-bold text-secondary-700 mb-4">
</h2>
<p className="text-secondary-600 mb-8">
</p>
<Link href="/" className="btn-primary">
</Link>
</div>
</div>
);
}

View File

@@ -1,286 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
import { productCategories, siteConfig } from '@/data/site-config';
export default function HomePage() {
// Featured products with proper images - manually selected for variety
const featuredProducts = [
productCategories.find(p => p.id === 'ppr-elephant')!,
productCategories.find(p => p.id === 'hdpe')!,
productCategories.find(p => p.id === 'valve')!,
productCategories.find(p => p.id === 'grilles')!,
productCategories.find(p => p.id === 'thermobreak')!,
productCategories.find(p => p.id === 'upvc')!,
];
return (
<>
{/* Hero Section */}
<section className="relative h-[70vh] min-h-[500px] bg-secondary-900">
<div className="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-900/90 to-secondary-900/60 z-10" />
<Image
src="/images/2021/03/ppr-pipe_000C.jpg"
alt="ท่อพีพีอาร์คุณภาพสูง"
fill
className="object-cover opacity-50"
priority
/>
<div className="relative z-20 container mx-auto px-4 h-full flex items-center">
<div className="max-w-2xl">
<span className="inline-block px-4 py-2 bg-primary-600 text-white font-semibold mb-4 rounded">
HVAC
</span>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-6 leading-tight">
HVAC
<span className="text-primary-400 block"></span>
</h1>
<p className="text-lg md:text-xl text-secondary-200 mb-8">
PPR, HDPE, ,
</p>
<div className="flex flex-wrap gap-4">
<Link href="/product" className="btn-primary">
</Link>
<Link href="/contact-us" className="btn-outline border-white text-white hover:bg-white hover:text-secondary-900">
</Link>
</div>
</div>
</div>
</section>
{/* Features Section */}
<section className="py-16 bg-secondary-800">
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div className="text-center p-6">
<div className="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
</div>
<h3 className="text-xl font-bold text-white mb-2"></h3>
<p className="text-secondary-300">
</p>
</div>
<div className="text-center p-6">
<div className="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<h3 className="text-xl font-bold text-white mb-2"></h3>
<p className="text-secondary-300">
</p>
</div>
<div className="text-center p-6">
<div className="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
<h3 className="text-xl font-bold text-white mb-2"></h3>
<p className="text-secondary-300">
</p>
</div>
</div>
</div>
</section>
{/* Highlight Products Section */}
<section className="py-16 bg-secondary-50">
<div className="container mx-auto px-4">
<div className="text-center mb-12">
<h2 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h2>
<p className="text-secondary-600 text-lg"></p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{/* PPR Pipe */}
<Link href="/ท่อพีพีอาร์ตราช้าง" className="group relative overflow-hidden rounded-2xl aspect-[4/5] bg-secondary-900">
<Image
src="/images/2021/03/ppr-pipe_000C.jpg"
alt="ท่อ PPR ตราช้าง"
fill
className="object-cover group-hover:scale-110 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-gradient-to-t from-secondary-900 via-secondary-900/40 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-6">
<span className="inline-block px-3 py-1 bg-primary-600 text-white text-sm font-semibold rounded mb-3"> | Pipe</span>
<h3 className="text-2xl font-bold text-white mb-2"> PPR </h3>
<p className="text-secondary-200 text-sm mb-4"> SCG DIN 8077/8078 20 50+ </p>
<span className="inline-flex items-center gap-2 text-primary-400 font-semibold group-hover:text-primary-300 transition-colors">
<svg className="w-4 h-4 group-hover:translate-x-2 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</span>
</div>
</Link>
{/* Grilles / Air Diffuser */}
<Link href="/หัวจ่ายลม-กริล" className="group relative overflow-hidden rounded-2xl aspect-[4/5] bg-secondary-900">
<Image
src="/images/2021/03/grilles_000C.jpg"
alt="กริลแอร์พลาสติก"
fill
className="object-cover group-hover:scale-110 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-gradient-to-t from-secondary-900 via-secondary-900/40 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-6">
<span className="inline-block px-3 py-1 bg-primary-600 text-white text-sm font-semibold rounded mb-3"></span>
<h3 className="text-2xl font-bold text-white mb-2"></h3>
<p className="text-secondary-200 text-sm mb-4"> Ball Jet </p>
<span className="inline-flex items-center gap-2 text-primary-400 font-semibold group-hover:text-primary-300 transition-colors">
<svg className="w-4 h-4 group-hover:translate-x-2 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</span>
</div>
</Link>
{/* Thermobreak */}
<Link href="/เทอร์โมเบรค-thermobreak" className="group relative overflow-hidden rounded-2xl aspect-[4/5] bg-secondary-900">
<Image
src="/images/2025/01/thermobrek_cover_000C.jpg"
alt="เทอร์โมเบรค Thermobreak"
fill
className="object-cover group-hover:scale-110 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-gradient-to-t from-secondary-900 via-secondary-900/40 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-6">
<span className="inline-block px-3 py-1 bg-primary-600 text-white text-sm font-semibold rounded mb-3"></span>
<h3 className="text-2xl font-bold text-white mb-2"></h3>
<p className="text-secondary-200 text-sm mb-4"> Polyolefin Foam FM/UL HVAC </p>
<span className="inline-flex items-center gap-2 text-primary-400 font-semibold group-hover:text-primary-300 transition-colors">
<svg className="w-4 h-4 group-hover:translate-x-2 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</span>
</div>
</Link>
</div>
</div>
</section>
{/* Featured Products Section */}
<section className="py-16">
<div className="container mx-auto px-4">
<div className="text-center mb-12">
<h2 className="section-title">
<span className="text-primary-600"></span>
</h2>
<p className="section-subtitle">
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{featuredProducts.map((product) => (
<Link
key={product.id}
href={product.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={product.image}
alt={product.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute top-4 left-4">
<span className="industrial-badge">{product.nameEn}</span>
</div>
</div>
<div className="p-6">
<h3 className="text-xl font-bold text-secondary-900 mb-2 group-hover:text-primary-600 transition-colors">
{product.name}
</h3>
<p className="text-secondary-600 text-sm mb-4">
{product.shortDescription || product.description.slice(0, 100) + '...'}
</p>
<span className="text-primary-600 font-semibold flex items-center gap-2">
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</span>
</div>
</Link>
))}
</div>
<div className="text-center mt-12">
<Link href="/product" className="btn-secondary">
</Link>
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-16 bg-primary-600">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
?
</h2>
<p className="text-primary-100 text-lg mb-8 max-w-2xl mx-auto">
</p>
<div className="flex flex-wrap justify-center gap-4">
<a
href={`tel:${siteConfig.phone}`}
className="btn-secondary bg-white text-primary-600 hover:bg-primary-50"
>
: {siteConfig.phone}
</a>
<Link href="/contact-us" className="btn-outline border-white text-white hover:bg-white hover:text-primary-600">
</Link>
</div>
</div>
</section>
{/* About Section */}
<section className="py-16">
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h2 className="section-title mb-6">
<span className="text-primary-600">{siteConfig.name}</span>
</h2>
<p className="text-secondary-600 mb-4">
{siteConfig.nameTh}
10
</p>
<p className="text-secondary-600 mb-6">
HDPE PVC
</p>
<Link href="/about-us" className="btn-primary">
</Link>
</div>
<div className="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<Image
src="/images/2021/03/hdpe-pipe_000C.jpg"
alt="เกี่ยวกับดีลพลัสเทค"
fill
className="object-cover"
/>
</div>
</div>
</div>
</section>
</>
);
}

View File

@@ -1,101 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
import { productCategories } from '@/data/site-config';
export const metadata = {
title: 'ท่อ | Pipe - ดีลพลัสเทค',
description: 'จำหน่ายท่อทุกประเภท ท่อ PPR ท่อ HDPE ท่อ PVC ท่อ uPVC ท่อไซเลอร์ คุณภาพสูง ราคาถูก',
};
// Pipe category product IDs
const pipeProductIds = [
'ppr-elephant',
'thai-ppr',
'poloplast',
'hdpe',
'upvc',
'pvc',
'syler',
'xylent',
'ppr-welder',
];
export default function PipePage() {
const pipeProducts = productCategories.filter(p => pipeProductIds.includes(p.id));
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium"> | Pipe</li>
</ol>
</nav>
{/* Header */}
<div className="mb-12">
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
| Pipe
</h1>
<p className="text-secondary-600 text-lg max-w-3xl">
PPR SCG HDPE PE80/PE100 PVC uPVC
.
</p>
</div>
{/* Products Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{pipeProducts.map((product) => (
<Link
key={product.id}
href={product.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={product.image}
alt={product.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-4">
<span className="text-xs text-primary-600 font-semibold">
{product.nameEn}
</span>
<h2 className="text-lg font-bold text-secondary-900 mt-1 group-hover:text-primary-600 transition-colors">
{product.name}
</h2>
<p className="text-sm text-secondary-600 mt-2 line-clamp-2">
{product.shortDescription || product.description}
</p>
</div>
</Link>
))}
</div>
{/* CTA */}
<div className="mt-12 text-center">
<p className="text-secondary-600 mb-4">
?
</p>
<div className="flex justify-center gap-4">
<Link href="/contact-us" className="btn-primary">
</Link>
<a href="tel:090-555-1415" className="btn-outline">
090-555-1415
</a>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,130 +0,0 @@
import Image from 'next/image';
export const metadata = {
title: 'ผลงานของเรา',
description: 'ผลงานโครงการต่างๆ ที่ดีลพลัสเทคได้ร่วมเป็นส่วนหนึ่ง',
};
const portfolioItems = [
{
title: 'Cyber World',
category: 'อาคารพาณิชย์',
image: '/images/2021/02/IMG_3089.jpg',
},
{
title: 'Toyox',
category: 'อุตสาหกรรม',
image: '/images/2021/02/IMG_2226.jpg',
},
{
title: 'PPR PIPE',
category: 'ท่อ PPR',
image: '/images/2021/02/Image1.jpg',
},
{
title: 'โรงงานเอธานอล',
category: 'อุตสาหกรรม',
image: '/images/2021/02/ลพบุรี5.jpg',
},
{
title: 'บจก.หยั่น หว่อ หยุ่น',
category: 'อุตสาหกรรม',
image: '/images/2021/02/สมุทรสาคร2.jpg',
},
{
title: 'ซีคอนบางแค',
category: 'อาคารพาณิชย์',
image: '/images/2021/02/บางแค1.jpg',
},
{
title: 'ซีพีแรม ลาดกระบัง',
category: 'อาคารพาณิชย์',
image: '/images/2021/02/ลาดกระบัง1.jpg',
},
{
title: 'ซีพีแรม (บ่อเงิน)',
category: 'อาคารพาณิชย์',
image: '/images/2021/02/บ่อเงิน3.jpg',
},
{
title: 'บริษัท บีกริม',
category: 'อุตสาหกรรม',
image: '/images/2021/02/บีกริม-จำกัด-e1503304339753.jpg',
},
{
title: 'เอฟแอนด์เอฟ ฟูด',
category: 'อาหาร',
image: '/images/2021/02/เอฟแอนดืเอฟ2-horz.jpg',
},
{
title: 'Eminent Air Factory',
category: 'อุตสาหกรรม',
image: '/images/2021/02/บางพลี1-horz.jpg',
},
{
title: 'ไทยน้ำทิพย์',
category: 'อุตสาหกรรม',
image: '/images/2021/02/ไทยน้ำทิพย์1-horz.jpg',
},
{
title: 'Essilor Factory',
category: 'อุตสาหกรรม',
image: '/images/2021/02/Essilor1-horz.jpg',
},
{
title: 'Dog Food Factory',
category: 'อาหาร',
image: '/images/2021/02/บ.เอเชี่ยน1.jpg',
},
{
title: 'โครงการประชารัฐ',
category: 'ภาครัฐ',
image: '/images/2021/02/ประชารัฐ1-e1503323597848.jpg',
},
];
export default function PortfolioPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Hero */}
<div className="text-center mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h1>
<p className="text-xl text-secondary-600 max-w-2xl mx-auto">
</p>
</div>
{/* Portfolio Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{portfolioItems.map((item, index) => (
<div key={index} className="card group cursor-pointer overflow-hidden">
<div className="relative aspect-video bg-secondary-100 overflow-hidden">
<Image
src={item.image}
alt={item.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
{/* Hover Overlay */}
<div className="absolute inset-0 bg-gradient-to-t from-secondary-900/80 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
{/* Hover Text - hidden by default, slides up on hover */}
<div className="absolute bottom-0 left-0 right-0 p-4 translate-y-full group-hover:translate-y-0 transition-transform duration-300">
<span className="text-primary-400 text-sm">{item.category}</span>
<h3 className="text-white font-bold">{item.title}</h3>
</div>
</div>
{/* Static Info - only visible when NOT hovering */}
<div className="p-4 bg-white group-hover:hidden">
<span className="text-xs text-primary-600 font-semibold">{item.category}</span>
<h3 className="text-lg font-bold text-secondary-900 mt-1">{item.title}</h3>
</div>
</div>
))}
</div>
</div>
</div>
);
}

View File

@@ -1,493 +0,0 @@
import type { Metadata } from 'next';
import Link from 'next/link';
export const metadata: Metadata = {
title: 'นโยบายความเป็นส่วนตัว (Privacy Policy)',
description: 'นโยบายความเป็นส่วนตัวของบริษัท ดีล พลัส เทค จำกัด ตามพระราชบัญญัติคุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562 (PDPA)',
keywords: ['นโยบายความเป็นส่วนตัว', 'PDPA', 'คุ้มครองข้อมูลส่วนบุคคล', 'ดีลพลัสเทค'],
};
function PrivacyPolicySchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'LegalService',
name: 'ดีลพลัสเทค',
alternateName: 'Deal Plus Tech Co., Ltd.',
description: 'นโยบายความเป็นส่วนตัว - ตามพระราชบัญญัติคุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562 (PDPA)',
url: 'https://dealplustech.co.th/privacy-policy',
provider: {
'@type': 'Organization',
name: 'บริษัท ดีล พลัส เทค จำกัด',
telephone: '+66-90-555-1415',
email: 'info@dealplustech.co.th',
address: {
'@type': 'PostalAddress',
streetAddress: '9/70 ซอยนครลุง 17',
addressLocality: 'แขวงบางไผ่',
addressRegion: 'เขตบางแค',
addressCountry: 'TH',
postalCode: '10160',
},
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
export default function PrivacyPolicyPage() {
return (
<>
<PrivacyPolicySchema />
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Hero */}
<div className="text-center mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h1>
<p className="text-xl text-secondary-600 max-w-2xl mx-auto">
.. 2562 (PDPA)
</p>
<p className="text-sm text-secondary-500 mt-2">
ปรับปรุงล่าสุด: 9 2569
</p>
</div>
{/* Table of Contents */}
<div className="max-w-4xl mx-auto mb-12">
<div className="bg-secondary-50 rounded-2xl p-6 border border-secondary-200">
<h2 className="text-lg font-bold text-secondary-900 mb-4"></h2>
<nav className="space-y-2">
{[
{ num: '1', label: 'ข้อมูลผู้ควบคุมข้อมูลส่วนบุคคล', href: '#controller' },
{ num: '2', label: 'ประเภทข้อมูลที่เก็บรวบรวม', href: '#collection' },
{ num: '3', label: 'วัตถุประสงค์การเก็บรวบรวมข้อมูล', href: '#purpose' },
{ num: '4', label: 'ฐานทางกฎหมายสำหรับการประมวลผล', href: '#legal-basis' },
{ num: '5', label: 'ระยะเวลาเก็บรักษาข้อมูล', href: '#retention' },
{ num: '6', label: 'การเปิดเผยข้อมูล', href: '#disclosure' },
{ num: '7', label: 'การโอนข้อมูลข้ามประเทศ', href: '#transfer' },
{ num: '8', label: 'การตัดสินใจโดยอัตโนมัติ', href: '#automated' },
{ num: '9', label: 'คุกกี้และเทคโนโลยีการติดตาม', href: '#cookies' },
{ num: '10', label: 'สิทธิของเจ้าของข้อมูล', href: '#rights' },
{ num: '11', label: 'มาตรการรักษาความปลอดภัย', href: '#security' },
{ num: '12', label: 'ติดต่อเจ้าหน้าที่คุ้มครองข้อมูลส่วนบุคคล (DPO)', href: '#dpo' },
{ num: '13', label: 'สิทธิร้องเรียน', href: '#complaint' },
{ num: '14', label: 'การแก้ไขนโยบาย', href: '#amendment' },
].map((item) => (
<a
key={item.num}
href={item.href}
className="flex items-center gap-3 text-secondary-700 hover:text-primary-600 py-1 transition-colors"
>
<span className="w-8 h-8 bg-primary-600 text-white rounded-full flex items-center justify-center text-sm font-semibold">
{item.num}
</span>
<span>{item.label}</span>
</a>
))}
</nav>
</div>
</div>
{/* Content */}
<div className="max-w-4xl mx-auto space-y-8">
{/* Section 1 */}
<section id="controller" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
1.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
<strong> </strong> .. 2562 (PDPA)
</p>
<div className="bg-secondary-50 rounded-xl p-6 mt-4">
<h3 className="font-bold text-secondary-900 mb-3"></h3>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<span className="text-primary-600">📍</span>
<span>9/70 17 10160</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary-600">📞</span>
<span>090-555-1415</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary-600"></span>
<span>info@dealplustech.co.th</span>
</li>
</ul>
</div>
</div>
</section>
{/* Section 2 */}
<section id="collection" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
2.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>:</p>
<div className="grid md:grid-cols-2 gap-4 mt-4">
<div className="bg-primary-50 rounded-xl p-5 border border-primary-100">
<h3 className="font-bold text-primary-800 mb-2"></h3>
<ul className="space-y-1 text-secondary-700">
<li> -</li>
<li> </li>
<li> </li>
<li> </li>
<li> /</li>
</ul>
</div>
<div className="bg-secondary-50 rounded-xl p-5 border border-secondary-100">
<h3 className="font-bold text-secondary-800 mb-2"></h3>
<ul className="space-y-1 text-secondary-700">
<li> </li>
<li> IP Address</li>
<li> </li>
<li> </li>
<li> </li>
</ul>
</div>
</div>
</div>
</section>
{/* Section 3 */}
<section id="purpose" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
3.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>:</p>
<ul className="space-y-3 mt-4">
{[
'ให้บริการและตอบคำถามเกี่ยวกับสินค้าและบริการ',
'ปรับปรุงและพัฒนาประสบการณ์การใช้งานเว็บไซต์',
'ส่งข้อมูลข่าวสารและโปรโมชั่น (เมื่อได้รับความยินยอม)',
'ดำเนินการตามคำขอและการสั่งซื้อสินค้า',
'วิเคราะห์ข้อมูลเพื่อพัฒนาบริการที่ดีขึ้น',
'ปฏิบัติตามกฎหมายและข้อกำหนดที่เกี่ยวข้อง',
].map((item, index) => (
<li key={index} className="flex items-start gap-3">
<span className="w-6 h-6 bg-primary-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0 mt-0.5">
{index + 1}
</span>
<span>{item}</span>
</li>
))}
</ul>
</div>
</section>
{/* Section 4 */}
<section id="legal-basis" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
4.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>:</p>
<div className="space-y-4 mt-4">
<div className="border-l-4 border-primary-600 pl-4">
<h3 className="font-bold text-secondary-900"> (Consent)</h3>
<p> </p>
</div>
<div className="border-l-4 border-secondary-400 pl-4">
<h3 className="font-bold text-secondary-900"> (Contract)</h3>
<p></p>
</div>
<div className="border-l-4 border-primary-400 pl-4">
<h3 className="font-bold text-secondary-900"> (Legitimate Interest)</h3>
<p></p>
</div>
<div className="border-l-4 border-secondary-300 pl-4">
<h3 className="font-bold text-secondary-900"> (Legal Obligation)</h3>
<p></p>
</div>
</div>
</div>
</section>
{/* Section 5 */}
<section id="retention" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
5.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>:</p>
<div className="bg-red-50 rounded-xl p-6 border border-red-100 mt-4">
<ul className="space-y-3">
<li className="flex items-start gap-3">
<span className="text-red-600 font-bold"></span>
<span><strong>:</strong> 10 </span>
</li>
<li className="flex items-start gap-3">
<span className="text-red-600 font-bold"></span>
<span><strong>:</strong> 3 </span>
</li>
<li className="flex items-start gap-3">
<span className="text-red-600 font-bold"></span>
<span><strong>:</strong> </span>
</li>
</ul>
</div>
<p className="text-sm text-secondary-500">
</p>
</div>
</section>
{/* Section 6 */}
<section id="disclosure" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
6.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p> :</p>
<ul className="space-y-3 mt-4">
<li className="flex items-start gap-3">
<span className="w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0"></span>
<span></span>
</li>
<li className="flex items-start gap-3">
<span className="w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0"></span>
<span></span>
</li>
<li className="flex items-start gap-3">
<span className="w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0"></span>
<span></span>
</li>
<li className="flex items-start gap-3">
<span className="w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0"></span>
<span> () </span>
</li>
</ul>
</div>
</section>
{/* Section 7 */}
<section id="transfer" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
7.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
</p>
<div className="bg-yellow-50 rounded-xl p-4 border border-yellow-100 mt-4">
<p className="text-secondary-700">
<strong>:</strong>
</p>
</div>
</div>
</section>
{/* Section 8 */}
<section id="automated" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
8.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
(Profiling)
</p>
<div className="bg-secondary-50 rounded-xl p-4 border border-secondary-100 mt-4">
<p className="text-secondary-700">
<strong>:</strong>
</p>
</div>
</div>
</section>
{/* Section 9 */}
<section id="cookies" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
9.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
</p>
<div className="mt-4">
<Link
href="/cookie-policy"
className="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 font-semibold"
>
<span></span>
<span></span>
</Link>
</div>
</div>
</section>
{/* Section 10 - 8 Rights */}
<section id="rights" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
10. (8 PDPA)
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p> .. 2562 :</p>
<div className="grid md:grid-cols-2 gap-4 mt-6">
{[
{ num: '1', title: 'สิทธิในการเข้าถึง', desc: 'ขอเข้าถึงและขอรับสำเนาข้อมูลส่วนบุคคลของท่าน' },
{ num: '2', title: 'สิทธิในการแก้ไข', desc: 'ขอให้แก้ไขข้อมูลที่ไม่ถูกต้องหรือไม่สมบูรณ์' },
{ num: '3', title: 'สิทธิในการลบ', desc: 'ขอให้ลบข้อมูลเมื่อหมดความจำเป็นหรือเพิกถอนความยินยอม' },
{ num: '4', title: 'สิทธิในการระงับการใช้', desc: 'ขอให้ระงับการใช้ข้อมูลชั่วคราว' },
{ num: '5', title: 'สิทธิในการโอนย้าย', desc: 'ขอรับข้อมูลในรูปแบบที่อ่านได้ด้วยเครื่อง' },
{ num: '6', title: 'สิทธิในการคัดค้าน', desc: 'คัดค้านการประมวลผลที่อาจกระทบ' },
{ num: '7', title: 'สิทธิเพิกถอนความยินยอม', desc: 'เพิกถอนความยินยอมเมื่อใดก็ได้' },
{ num: '8', title: 'สิทธิในการร้องเรียน', desc: 'ร้องเรียนต่อหน่วยงานกำกับดูแล' },
].map((item) => (
<div key={item.num} className="bg-secondary-50 rounded-xl p-4 border border-secondary-100">
<div className="flex items-start gap-3">
<span className="w-8 h-8 bg-primary-600 text-white rounded-full flex items-center justify-center font-bold flex-shrink-0">
{item.num}
</span>
<div>
<h3 className="font-bold text-secondary-900">{item.title}</h3>
<p className="text-sm text-secondary-600">{item.desc}</p>
</div>
</div>
</div>
))}
</div>
<div className="bg-primary-50 rounded-xl p-6 border border-primary-100 mt-6">
<p className="text-secondary-700">
<strong>:</strong>
</p>
</div>
</div>
</section>
{/* Section 11 */}
<section id="security" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
11.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>:</p>
<ul className="space-y-3 mt-4">
{[
'เข้ารหัสข้อมูลด้วยมาตรฐาน SSL/TLS',
'จำกัดการเข้าถึงข้อมูลเฉพาะพนักงานที่ได้รับอนุญาต',
'ใช้ระบบ Firewall และ Antivirus',
'จัดเก็บข้อมูลในระบบที่มีการควบคุมการเข้าถึง',
'ทำลายข้อมูลอย่างปลอดภัยเมื่อหมดระยะเวลาการเก็บรักษา',
'ตรวจสอบและอัปเดตมาตรการรักษาความปลอดภัยเป็นระยะ',
].map((item, index) => (
<li key={index} className="flex items-start gap-3">
<span className="w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-sm flex-shrink-0"></span>
<span>{item}</span>
</li>
))}
</ul>
</div>
</section>
{/* Section 12 */}
<section id="dpo" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
12. (DPO)
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p> :</p>
<div className="bg-secondary-50 rounded-xl p-6 border border-secondary-100 mt-4">
<ul className="space-y-2">
<li className="flex items-start gap-2">
<span className="text-primary-600"></span>
<span>อีเมล: info@dealplustech.co.th</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary-600">📞</span>
<span>โทรศัพท์: 090-555-1415</span>
</li>
</ul>
</div>
</div>
</section>
{/* Section 13 */}
<section id="complaint" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
13.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
</p>
<div className="bg-yellow-50 rounded-xl p-6 border border-yellow-100 mt-4">
<h3 className="font-bold text-secondary-900 mb-3"></h3>
<ul className="space-y-2">
<li>📍 </li>
<li>📞 หมายเลขโทรศัพท์: 0-2142-1033-4</li>
<li> อีเมล: pdpc@oipd.go.th</li>
<li>🌐 เว็บไซต์: www.oipd.go.th</li>
</ul>
</div>
</div>
</section>
{/* Section 14 */}
<section id="amendment" className="bg-white rounded-2xl p-8 shadow-sm border border-secondary-100">
<h2 className="text-2xl font-bold text-secondary-900 mb-4">
14.
</h2>
<div className="space-y-4 text-lg text-secondary-700 leading-relaxed">
<p>
</p>
<div className="bg-secondary-50 rounded-xl p-4 border border-secondary-100 mt-4">
<p className="text-secondary-700">
<strong>:</strong> 1.0<br />
<strong>:</strong> 9 2569
</p>
</div>
</div>
</section>
{/* Contact CTA */}
<div className="bg-primary-600 rounded-2xl p-8 text-center">
<h2 className="text-2xl font-bold text-white mb-4">?</h2>
<p className="text-primary-100 mb-6 text-lg">
</p>
<div className="flex flex-wrap justify-center gap-4">
<a
href="tel:0905551415"
className="inline-flex items-center gap-2 bg-white text-primary-600 px-6 py-3 rounded-full font-semibold hover:bg-primary-50 transition-colors"
>
📞 090-555-1415
</a>
<a
href="mailto:info@dealplustech.co.th"
className="inline-flex items-center gap-2 bg-primary-700 text-white px-6 py-3 rounded-full font-semibold hover:bg-primary-800 transition-colors"
>
info@dealplustech.co.th
</a>
</div>
</div>
</div>
</div>
</div>
</>
);
}

View File

@@ -1,65 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
import { productCategories } from '@/data/site-config';
export const metadata = {
title: 'สินค้า - ท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว อุปกรณ์ท่อ',
description: 'สินค้าครบวงจร ท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว อุปกรณ์แขวนท่อ อุปกรณ์ปรับอากาศ และอุปกรณ์ดับเพลิง',
};
export default function ProductPage() {
// Group products by category
const categories = productCategories.reduce((acc, product) => {
const cat = product.slug;
if (!acc[cat]) {
acc[cat] = [];
}
acc[cat].push(product);
return acc;
}, {} as Record<string, typeof productCategories>);
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Page Header */}
<div className="text-center mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
<span className="text-primary-600"></span>
</h1>
<p className="text-xl text-secondary-600 max-w-2xl mx-auto">
</p>
</div>
{/* Products Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{productCategories.map((product) => (
<Link
key={product.id}
href={product.href}
className="card group"
>
<div className="relative aspect-video bg-secondary-100">
<Image
src={product.image}
alt={product.name}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-4">
<span className="text-xs text-primary-600 font-semibold">{product.nameEn}</span>
<h3 className="text-lg font-bold text-secondary-900 mt-1 group-hover:text-primary-600 transition-colors">
{product.name}
</h3>
<p className="text-secondary-600 text-sm mt-2 line-clamp-2">
{product.shortDescription || product.description}
</p>
</div>
</Link>
))}
</div>
</div>
</div>
);
}

View File

@@ -1,146 +0,0 @@
import Link from 'next/link';
export const metadata = {
title: 'Sales Engineer - วิศวกรฝ่ายขาย - ดีลพลัสเทค',
description: 'สมัครงานตำแหน่ง Sales Engineer ที่ดีลพลัสเทค รับผิดชอบการขายและให้คำปรึกษาด้านเทคนิคสำหรับผลิตภัณฑ์ท่อและอุปกรณ์ระบบท่อ',
};
export default function SalesEngineerPage() {
return (
<div className="pt-32 pb-16">
<div className="container mx-auto px-4">
{/* Breadcrumb */}
<nav className="mb-6">
<ol className="flex items-center gap-2 text-sm">
<li>
<Link href="/" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li>
<Link href="/join-us" className="text-secondary-500 hover:text-primary-600">
</Link>
</li>
<li className="text-secondary-400">/</li>
<li className="text-primary-600 font-medium">Sales Engineer</li>
</ol>
</nav>
{/* Header */}
<div className="mb-8">
<div className="flex flex-wrap gap-2 mb-4">
<span className="px-3 py-1 bg-secondary-100 text-secondary-700 rounded-full text-sm">
Full-time
</span>
<span className="px-3 py-1 bg-secondary-100 text-secondary-700 rounded-full text-sm">
</span>
<span className="px-3 py-1 bg-primary-100 text-primary-700 rounded-full text-sm">
</span>
</div>
<h1 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-2">
Sales Engineer
</h1>
<p className="text-xl text-primary-600"></p>
</div>
{/* Content */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2">
{/* Job Description */}
<div className="bg-white rounded-xl p-6 shadow-card mb-6">
<h2 className="text-xl font-bold text-secondary-900 mb-4">
</h2>
<p className="text-secondary-600 mb-4">
</p>
<h3 className="font-semibold text-secondary-900 mb-2">:</h3>
<ul className="list-disc list-inside text-secondary-600 space-y-2 mb-4">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
{/* Requirements */}
<div className="bg-white rounded-xl p-6 shadow-card mb-6">
<h2 className="text-xl font-bold text-secondary-900 mb-4">
</h2>
<ul className="list-disc list-inside text-secondary-600 space-y-2">
<li> </li>
<li> 1-3 Sales Engineer</li>
<li></li>
<li></li>
<li> </li>
<li></li>
</ul>
</div>
{/* Benefits */}
<div className="bg-white rounded-xl p-6 shadow-card">
<h2 className="text-xl font-bold text-secondary-900 mb-4">
</h2>
<ul className="list-disc list-inside text-secondary-600 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li> (-)</li>
<li> </li>
</ul>
</div>
</div>
{/* Sidebar */}
<div className="lg:col-span-1">
<div className="bg-primary-50 rounded-xl p-6 sticky top-24">
<h3 className="text-lg font-bold text-secondary-900 mb-4">
?
</h3>
<p className="text-secondary-600 mb-4">
:
</p>
<div className="space-y-4">
<a
href="mailto:info@dealplustech.co.th?subject=Apply for Sales Engineer Position"
className="btn-primary w-full block text-center"
>
</a>
<a
href="tel:090-555-1415"
className="btn-outline w-full block text-center"
>
090-555-1415
</a>
<Link
href="/contact-us"
className="btn-outline w-full block text-center"
>
</Link>
</div>
<div className="mt-6 pt-6 border-t border-primary-200">
<p className="text-sm text-secondary-600">
<strong>:</strong><br />
<br />
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,263 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
export const metadata = {
title: 'บริการของเรา',
description: 'บริการครบวงจร จำหน่ายวัสดุท่อ ให้คำปรึกษา ออกแบบระบบ และติดตั้ง',
};
const services = [
{
title: 'จำหน่ายวัสดุท่อ',
description: 'จำหน่ายท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร สินค้าคุณภาพ ราคาแข่งขันได้',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
),
},
{
title: 'ให้คำปรึกษา',
description: 'ทีมงานมืออาชีพพร้อมให้คำปรึกษาเกี่ยวกับการเลือกวัสดุท่อที่เหมาะสมกับโครงการของคุณ',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
),
},
{
title: 'ออกแบบระบบ',
description: 'บริการออกแบบระบบท่อน้ำ ระบบดับเพลิง และระบบปรับอากาศ โดยวิศวกรผู้เชี่ยวชาญ',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" />
</svg>
),
},
{
title: 'ติดตั้งระบบ',
description: 'ทีมช่างผู้เชี่ยวชาญติดตั้งระบบท่อครบวงจร พร้อมรับประกันงาน',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
),
},
{
title: 'จัดส่งสินค้า',
description: 'บริการจัดส่งสินค้าทั่วประเทศ รวดเร็ว ปลอดภัย มีประกันความเสียหาย',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
),
},
{
title: 'บริการหลังการขาย',
description: 'ทีมงานพร้อมให้การดูแลและบริการซ่อมบำรุงหลังการขายตลอดอายุการใช้งาน',
icon: (
<svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
),
},
];
const processSteps = [
{
step: '01',
title: 'ปรึกษา',
description: 'ติดต่อเราเพื่อปรึกษาเกี่ยวกับความต้องการของโครงการ',
},
{
step: '02',
title: 'ออกแบบ',
description: 'ทีมวิศวกรออกแบบระบบให้เหมาะสมกับการใช้งาน',
},
{
step: '03',
title: 'เสนอราคา',
description: 'เสนอราคาสินค้าและบริการอย่างโปร่งใส',
},
{
step: '04',
title: 'ติดตั้ง',
description: 'ทีมช่างติดตั้งโดยมืออาชีพตรงตามกำหนด',
},
];
export default function ServicesPage() {
return (
<div className="pt-20">
{/* Hero Section */}
<section className="relative h-[50vh] min-h-[400px] bg-secondary-900">
<div className="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-900/90 to-secondary-900/60 z-10" />
<Image
src="/images/2021/03/hdpe-pipe_000C.jpg"
alt="บริการของเรา"
fill
className="object-cover opacity-40"
priority
/>
<div className="relative z-20 container mx-auto px-4 h-full flex items-center">
<div className="max-w-2xl">
<span className="inline-block px-4 py-2 bg-primary-600 text-white font-semibold mb-4 rounded">
</span>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-6">
<span className="text-primary-400"></span>
</h1>
<p className="text-xl text-secondary-200">
</p>
</div>
</div>
</section>
{/* Services Grid */}
<section className="py-20 bg-white">
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{services.map((service, index) => (
<div
key={index}
className="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl"
>
<div className="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
{service.icon}
</div>
<h3 className="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
{service.title}
</h3>
<p className="text-secondary-600 group-hover:text-primary-100 transition-colors">
{service.description}
</p>
</div>
))}
</div>
</div>
</section>
{/* Process Section */}
<section className="py-20 bg-secondary-900">
<div className="container mx-auto px-4">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
<span className="text-primary-400"></span>
</h2>
<p className="text-secondary-300 text-lg max-w-2xl mx-auto">
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{processSteps.map((item, index) => (
<div key={index} className="relative">
<div className="text-center">
<span className="text-6xl font-bold text-primary-600/30">{item.step}</span>
<h3 className="text-xl font-bold text-white mt-4 mb-2">{item.title}</h3>
<p className="text-secondary-400">{item.description}</p>
</div>
{index < processSteps.length - 1 && (
<div className="hidden lg:block absolute top-8 right-0 transform translate-x-1/2">
<svg className="w-8 h-8 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
)}
</div>
))}
</div>
</div>
</section>
{/* Why Choose Us */}
<section className="py-20 bg-secondary-50">
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h2 className="text-3xl md:text-4xl font-bold text-secondary-900 mb-6">
<span className="text-primary-600"></span>
</h2>
<div className="space-y-6">
<div className="flex gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 className="font-bold text-secondary-900 mb-1"> 10 </h3>
<p className="text-secondary-600"></p>
</div>
</div>
<div className="flex gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 className="font-bold text-secondary-900 mb-1"></h3>
<p className="text-secondary-600"> . / FM / UL </p>
</div>
</div>
<div className="flex gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 className="font-bold text-secondary-900 mb-1"></h3>
<p className="text-secondary-600"></p>
</div>
</div>
<div className="flex gap-4">
<div className="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 className="font-bold text-secondary-900 mb-1"></h3>
<p className="text-secondary-600"> </p>
</div>
</div>
</div>
</div>
<div className="relative aspect-video bg-secondary-200 rounded-2xl overflow-hidden">
<Image
src="/images/2021/03/hdpe-welding_000C-1.jpg"
alt="ทีมงานมืออาชีพ"
fill
className="object-cover"
/>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-20 bg-primary-600">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
?
</h2>
<p className="text-primary-100 text-lg mb-8 max-w-2xl mx-auto">
</p>
<div className="flex flex-wrap justify-center gap-4">
<Link href="/contact-us" className="btn-secondary bg-white text-primary-600 hover:bg-primary-50">
</Link>
<a href="tel:090-555-1415" className="btn-outline border-white text-white hover:bg-white hover:text-primary-600">
โทร: 090-555-1415
</a>
</div>
</div>
</section>
</div>
);
}

View File

@@ -1,118 +0,0 @@
import { MetadataRoute } from 'next';
import { productCategories, portfolioProjects, mainNavigation } from '@/data/site-config';
const BASE_URL = 'https://dealplustech.co.th';
export default function sitemap(): MetadataRoute.Sitemap {
const now = new Date();
// Static pages
const staticPages: MetadataRoute.Sitemap = [
{
url: BASE_URL,
lastModified: now,
changeFrequency: 'weekly',
priority: 1,
},
{
url: `${BASE_URL}/about-us/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${BASE_URL}/services/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${BASE_URL}/product/`,
lastModified: now,
changeFrequency: 'weekly',
priority: 0.9,
},
{
url: `${BASE_URL}/pipe/`,
lastModified: now,
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${BASE_URL}/portfolio/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.7,
},
{
url: `${BASE_URL}/blog/`,
lastModified: now,
changeFrequency: 'weekly',
priority: 0.7,
},
{
url: `${BASE_URL}/contact-us/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${BASE_URL}/join-us/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.5,
},
{
url: `${BASE_URL}/sales-engineer/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.5,
},
{
url: `${BASE_URL}/all-projects/`,
lastModified: now,
changeFrequency: 'monthly',
priority: 0.6,
},
];
// Product pages
const productPages: MetadataRoute.Sitemap = productCategories.map((product) => ({
url: `${BASE_URL}${product.href}`,
lastModified: now,
changeFrequency: 'weekly' as const,
priority: 0.8,
}));
// Portfolio pages
const portfolioPages: MetadataRoute.Sitemap = portfolioProjects.map((project) => ({
url: `${BASE_URL}${project.href}`,
lastModified: now,
changeFrequency: 'monthly' as const,
priority: 0.6,
}));
// Blog posts (Thai URLs)
const blogPages: MetadataRoute.Sitemap = [
{
url: `${BASE_URL}/blog/ข้อดี-ท่อ-hdpe/`,
lastModified: now,
changeFrequency: 'monthly' as const,
priority: 0.6,
},
{
url: `${BASE_URL}/blog/ท่อ-ppr-คืออะไร/`,
lastModified: now,
changeFrequency: 'monthly' as const,
priority: 0.6,
},
{
url: `${BASE_URL}/blog/บำรุงรักษาปั๊มน้ำ/`,
lastModified: now,
changeFrequency: 'monthly' as const,
priority: 0.6,
},
];
return [...staticPages, ...productPages, ...portfolioPages, ...blogPages];
}

View File

@@ -1,84 +0,0 @@
# COMPONENTS - UI & Layout
**Generated:** 2026-03-08
## OVERVIEW
Component architecture split into `ui/` (reusable primitives), `layout/` (structural), and `analytics/`. Tailwind + custom design system with industrial theme.
## STRUCTURE
```
src/components/
├── ui/ # Reusable UI primitives
│ ├── Button.tsx # Button variants (primary, secondary, outline)
│ ├── Card.tsx # Card containers (card, card-industrial)
│ └── Badge.tsx # Status badges
├── layout/ # Layout components
│ ├── Header.tsx # Fixed header with top bar + nav (201 lines)
│ ├── Footer.tsx # Footer with contact info
│ └── FloatingContact.tsx # LINE/phone floating buttons
└── analytics/
└── GoogleAnalytics.tsx # GA tracking
```
## WHERE TO LOOK
| Task | Location | Notes |
|------|----------|-------|
| Add UI component | `src/components/ui/{Component}.tsx` | Reusable across pages |
| Modify layout | `src/components/layout/` | Header, Footer, FloatingContact |
| Custom styles | `src/styles/globals.css` | `.btn-primary`, `.card-industrial`, etc. |
| Design tokens | `tailwind.config.js` | Colors, shadows, animations |
## CONVENTIONS
**Component pattern**:
```typescript
'use client' // If using useState/useEffect
import { cn } from '@/lib/utils'
import { siteConfig } from '@/data/site-config'
export default function Component() {
return (...)
}
```
**Class merging**: Use `cn()` utility for conditional classes:
```typescript
import { cn } from '@/lib/utils'
<div className={cn('base-class', isActive && 'active-class')} />
```
**Contact info**: Always use `siteConfig` from `@/data/site-config`, never hardcode.
**Top bar**: Header includes fixed top bar with phone/email/LINE (bg-primary-600).
## ANTI-PATTERNS (THIS PROJECT)
- **DO NOT** hardcode contact info - use `siteConfig` from `@/data/site-config`
- **DO NOT** use `as any` or `@ts-ignore` - strict mode enabled
- **DO NOT** import entire `site-config.ts` if only need one field - file is 149KB
## UNIQUE STYLES
**Design system** (tailwind.config.js):
- `primary-*`: Green (#22c55e) - trust, growth
- `secondary-*`: Slate grays - professional, industrial
- `accent-*`: Yellow - highlights
- `industrial-*`: Dark theme colors
**Custom shadows**:
- `shadow-industrial`: `0 10px 40px -10px rgba(0, 0, 0, 0.3)`
- `shadow-bold`: `0 4px 0 0 rgba(0, 0, 0, 0.2)`
- `shadow-card`: `0 4px 20px -2px rgba(0, 0, 0, 0.15)`
**Custom animations**: `fade-in`, `slide-up`, `slide-down`, `bounce-soft`
## NOTES
- **Kanit font**: Loaded in root layout, applied via `var(--font-kanit)`
- **No component index**: Import directly from file paths
- **Floating contact**: Fixed position LINE/phone buttons on mobile

View File

@@ -0,0 +1,51 @@
---
import type { CollectionEntry } from 'astro:content';
interface Props {
post: CollectionEntry<'blog'>;
}
const { post } = Astro.props;
const { title, excerpt, date, author, category, categories, image, featuredImage } = post.data;
// Support both 'category' and 'categories' field names
const postCategory = category || (Array.isArray(categories) ? categories[0] : 'ทั่วไป');
// Support both 'image' and 'featuredImage' field names
const postImage = image || featuredImage || '/images/2021/03/ppr-pipe_000C.jpg';
---
<a href={`/blog/${post.slug}`} class="card group">
<div class="relative aspect-video bg-secondary-100 overflow-hidden">
<img
src={postImage}
alt={title}
class="object-cover w-full h-48 group-hover:scale-105 transition-transform duration-300"
loading="lazy"
/>
<div class="absolute top-4 left-4">
<span class="industrial-badge">{postCategory}</span>
</div>
</div>
<div class="p-6">
<time class="text-sm text-secondary-500">
{new Date(date).toLocaleDateString('th-TH', { year: 'numeric', month: 'long', day: 'numeric' })}
</time>
<h3 class="mt-2 text-xl font-bold text-secondary-900 group-hover:text-primary-600 transition-colors line-clamp-2">
{title}
</h3>
{excerpt && (
<p class="mt-3 text-secondary-600 text-sm line-clamp-3">
{excerpt}
</p>
)}
<div class="mt-4 flex items-center text-primary-600 font-medium">
<span>อ่านต่อ</span>
<svg class="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</a>

View File

@@ -0,0 +1,29 @@
---
import { siteConfig } from '../data/site-config';
---
<div class="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"
class="w-14 h-14 bg-[#00B900] rounded-full flex items-center justify-center shadow-lg hover:scale-110 transition-transform"
aria-label="ติดต่อผ่าน LINE"
>
<svg class="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}`}
class="w-14 h-14 bg-primary-600 rounded-full flex items-center justify-center shadow-lg hover:scale-110 transition-transform"
aria-label="โทรหาเรา"
>
<svg class="w-7 h-7 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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>

114
src/components/Footer.astro Normal file
View File

@@ -0,0 +1,114 @@
---
import { siteConfig, workHours, mainNavigation } from '../data/site-config';
---
<footer class="bg-secondary-50 text-secondary-900">
<!-- Main Footer -->
<div class="container mx-auto px-4 py-12">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Company Info -->
<div>
<img
src="/images/2021/02/13523630950840.png"
alt="Deal Plus Tech"
class="h-10 w-auto mb-4"
/>
<p class="text-secondary-600 text-sm mb-4">
{siteConfig.description}
</p>
<div class="flex gap-3">
<a
href={siteConfig.facebookUrl}
target="_blank"
rel="noopener noreferrer"
class="w-10 h-10 bg-secondary-200 rounded-lg flex items-center justify-center text-secondary-700 hover:bg-primary-600 hover:text-white transition-colors"
aria-label="Facebook"
>
<svg class="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"
class="w-10 h-10 bg-secondary-200 rounded-lg flex items-center justify-center text-secondary-700 hover:bg-primary-600 hover:text-white transition-colors"
aria-label="LINE"
>
<svg class="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 class="text-lg font-bold mb-4 text-primary-600">ลิงก์ด่วน</h3>
<ul class="space-y-2">
{mainNavigation.slice(0, 5).map((item) => (
<li>
<a href={item.href} class="text-secondary-600 hover:text-primary-600 transition-colors">
{item.label}
</a>
</li>
))}
</ul>
</div>
<!-- Contact Info -->
<div>
<h3 class="text-lg font-bold mb-4 text-primary-600">ติดต่อเรา</h3>
<ul class="space-y-3">
<li class="flex items-start gap-3">
<svg class="w-5 h-5 text-primary-500 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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 stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span class="text-secondary-600 text-sm">{siteConfig.address}</span>
</li>
<li class="flex items-center gap-3">
<svg class="w-5 h-5 text-primary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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}`} class="text-secondary-600 hover:text-primary-600 text-sm">
{siteConfig.phone}
</a>
</li>
<li class="flex items-center gap-3">
<svg class="w-5 h-5 text-primary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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}`} class="text-secondary-600 hover:text-primary-600 text-sm">
{siteConfig.email}
</a>
</li>
</ul>
</div>
<!-- Business Hours -->
<div>
<h3 class="text-lg font-bold mb-4 text-primary-600">เวลาทำการ</h3>
<ul class="space-y-2">
{workHours.map((item) => (
<li class="flex justify-between text-sm">
<span class="text-secondary-600">{item.day}</span>
<span class={item.isClosed ? 'text-red-500' : 'text-secondary-900 font-medium'}>
{item.hours}
</span>
</li>
))}
</ul>
</div>
</div>
</div>
<!-- Bottom Bar -->
<div class="border-t border-secondary-200">
<div class="container mx-auto px-4 py-4">
<p class="text-center text-secondary-500 text-sm">
© {new Date().getFullYear()} {siteConfig.name}. สงวนลิขสิทธิ์.
</p>
</div>
</div>
</footer>

222
src/components/Header.astro Normal file
View File

@@ -0,0 +1,222 @@
---
import { siteConfig, mainNavigation } from '../data/site-config';
import { cn } from '../lib/utils';
interface NavItemWithChildren {
label: string;
href: string;
children?: Array<{
label: string;
href: string;
children?: Array<{ label: string; href: string }>;
}>;
}
const navItems = mainNavigation as NavItemWithChildren[];
---
<header class="fixed top-0 left-0 right-0 z-50 bg-white shadow-md">
<!-- Top Bar -->
<div class="bg-primary-600 py-2">
<div class="container mx-auto px-4 flex justify-between items-center text-sm">
<div class="flex items-center gap-6 text-white">
<a href={`tel:${siteConfig.phone}`} class="flex items-center gap-2 hover:text-primary-100">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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}`} class="flex items-center gap-2 hover:text-primary-100">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={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 class="hidden md:flex items-center gap-4">
<a href={`https://line.me/ti/p/${siteConfig.lineId}`} class="flex items-center gap-1 text-white hover:text-primary-100">
<svg class="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 class="container mx-auto px-4">
<div class="flex items-center justify-between h-16">
<!-- Logo -->
<a href="/" class="flex items-center gap-3">
<img
src="/images/2021/02/13523630950840.png"
alt="Deal Plus Tech"
class="h-12 w-auto"
loading="priority"
/>
</a>
<!-- Desktop Navigation -->
<div class="hidden lg:flex items-center gap-1">
{navItems.map((item) => (
<div class="relative group">
<a
href={item.href}
class:list={[
"px-4 py-2 text-secondary-700 font-medium hover:text-primary-600 transition-colors flex items-center gap-1",
item.children && "pr-2"
]}
>
{item.label}
{item.children && (
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M19 9l-7 7-7-7" />
</svg>
)}
</a>
<!-- Dropdown -->
{item.children && (
<div class="absolute top-full left-0 pt-2 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50">
<div class="absolute -top-2 left-0 right-0 h-2" />
<div class="min-w-[600px] bg-white shadow-xl rounded-lg py-4 border border-secondary-100">
<div class="grid grid-cols-2 gap-1 px-4">
{item.children.map((child) => (
<div class="relative group/sub">
<a
href={child.href}
class="block px-3 py-2 text-secondary-700 hover:bg-primary-50 hover:text-primary-700 transition-colors rounded font-medium"
>
{child.label}
</a>
{child.children && (
<div class="hidden group-hover/sub:block absolute left-full top-0 w-56 !bg-white shadow-xl rounded-lg py-2 border border-secondary-100 max-h-96 overflow-y-auto z-50">
<div class="absolute -top-2 -bottom-2 -left-2 w-2" />
{child.children.map((subChild) => (
<a
href={subChild.href}
class="block px-4 py-2 text-secondary-600 hover:bg-primary-50 hover:text-primary-700 text-sm"
>
{subChild.label}
</a>
))}
</div>
)}
</div>
))}
</div>
</div>
</div>
)}
</div>
))}
<a href="/contact-us" class="btn-primary ml-4">
ติดต่อเรา
</a>
</div>
<!-- Mobile Menu Button -->
<button
id="mobile-menu-button"
class="lg:hidden text-secondary-900 p-2"
aria-label="Toggle menu"
>
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="lg:hidden py-4 border-t border-secondary-200 max-h-[80vh] overflow-y-auto hidden">
{navItems.map((item) => (
item.children ? (
<div class="border-b border-secondary-100">
<div class="px-4 py-3 font-semibold text-secondary-900 bg-secondary-50">
{item.label}
</div>
<div class="pl-4">
{item.children.map((child) => (
<div>
<a
href={child.href}
class="block px-4 py-2 text-secondary-700 hover:text-primary-600 hover:bg-primary-50 mobile-link"
>
{child.label}
</a>
{child.children && (
<div class="pl-4 bg-secondary-50">
{child.children.map((subChild) => (
<a
href={subChild.href}
class="block px-4 py-2 text-secondary-600 hover:text-primary-600 text-sm mobile-link"
>
{subChild.label}
</a>
))}
</div>
)}
</div>
))}
</div>
</div>
) : (
<a
href={item.href}
class="block px-4 py-3 text-secondary-700 hover:text-primary-600 font-medium mobile-link"
>
{item.label}
</a>
)
))}
<div class="p-4">
<a
href="/contact-us"
class="btn-primary block text-center mobile-link"
>
ติดต่อเรา
</a>
</div>
</div>
</nav>
</header>
<script>
// Mobile menu toggle
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
let mobileMenuOpen = false;
mobileMenuButton?.addEventListener('click', () => {
mobileMenuOpen = !mobileMenuOpen;
if (mobileMenuOpen) {
mobileMenu?.classList.remove('hidden');
mobileMenuButton.innerHTML = `
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M6 18L18 6M6 6l12 12" />
</svg>
`;
} else {
mobileMenu?.classList.add('hidden');
mobileMenuButton.innerHTML = `
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
`;
}
});
// Close mobile menu when clicking links
document.querySelectorAll('.mobile-link').forEach(link => {
link.addEventListener('click', () => {
mobileMenuOpen = false;
mobileMenu?.classList.add('hidden');
mobileMenuButton.innerHTML = `
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
`;
});
});
</script>

View File

@@ -0,0 +1,37 @@
---
import type { CollectionEntry } from 'astro:content';
interface Props {
product: CollectionEntry<'products'>;
}
const { product } = Astro.props;
const { name, shortDescription, image } = product.data;
---
<a href={`/products/${product.data.slug}`} class="card group">
<div class="aspect-w-16 aspect-h-9 overflow-hidden bg-secondary-100">
<img
src={image || '/placeholder.jpg'}
alt={name}
class="object-cover w-full h-48 group-hover:scale-105 transition-transform duration-300"
loading="lazy"
/>
</div>
<div class="p-6">
<h3 class="text-lg font-bold text-secondary-900 group-hover:text-primary-600 transition-colors">
{name}
</h3>
{shortDescription && (
<p class="mt-2 text-sm text-secondary-600 line-clamp-2">
{shortDescription}
</p>
)}
<div class="mt-4 flex items-center text-primary-600 font-medium">
<span>ดูรายละเอียด</span>
<svg class="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</a>

View File

@@ -1,31 +0,0 @@
'use client';
import Script from 'next/script';
const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
export default function GoogleAnalytics() {
if (!GA_MEASUREMENT_ID || GA_MEASUREMENT_ID === 'G-XXXXXXXXXX') {
return null;
}
return (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_MEASUREMENT_ID}', {
page_title: document.title,
page_location: window.location.href,
});
`}
</Script>
</>
);
}

View File

@@ -0,0 +1,188 @@
---
---
<div id="consent-preferences-modal" class="fixed inset-0 z-50 hidden">
<div class="fixed inset-0 bg-black/50 transition-opacity" id="consent-modal-backdrop"></div>
<div class="fixed inset-0 flex items-center justify-center p-4">
<div class="relative bg-white rounded-xl shadow-2xl w-full max-w-lg max-h-[90vh] overflow-y-auto">
<div class="p-6">
<h2 class="text-xl font-semibold text-gray-900 mb-2">ตั้งค่าคุกกี้</h2>
<p class="text-sm text-gray-600 mb-6">
คุณสามารถปรับแต่งการตั้งค่าคุกกี้ได้ตามต้องการ
</p>
<div class="space-y-5">
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<span class="font-medium text-gray-900">จำเป็น (เปิดเสมอ)</span>
<p class="text-xs text-gray-500 mt-0.5">คุกกี้ที่จำเป็นสำหรับการทำงานของเว็บไซต์</p>
</div>
<label class="relative inline-flex items-center cursor-not-allowed">
<input type="checkbox" checked disabled class="sr-only peer" />
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
</label>
</div>
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<span class="font-medium text-gray-900">วิเคราะห์การใช้งาน</span>
<p class="text-xs text-gray-500 mt-0.5">ช่วยให้เราเข้าใจว่าผู้ใช้งานใช้เว็บไซต์อย่างไร</p>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" id="consent-analytics" class="sr-only peer" />
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
</label>
</div>
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<span class="font-medium text-gray-900">การตลาด</span>
<p class="text-xs text-gray-500 mt-0.5">ใช้สำหรับการตลาดและโฆษณา</p>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" id="consent-marketing" class="sr-only peer" />
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
</label>
</div>
</div>
<div class="mt-6 flex flex-col sm:flex-row gap-3">
<button
id="consent-save"
class="flex-1 px-5 py-2.5 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500"
>
บันทึกการตั้งค่า
</button>
<button
id="consent-close"
class="px-5 py-2.5 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400"
>
ยกเลิก
</button>
</div>
</div>
</div>
</div>
</div>
<script>
const POLICY_VERSION = '1.0';
const STORAGE_KEY = 'dealplustech_consent';
function generateSessionId(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getSessionId(): string {
let sessionId = localStorage.getItem('dealplustech_session');
if (!sessionId) {
sessionId = generateSessionId();
localStorage.setItem('dealplustech_session', sessionId);
}
return sessionId;
}
function getConsent(): { essential: boolean; analytics: boolean; marketing: boolean } | null {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
try {
return JSON.parse(stored);
} catch {
return null;
}
}
return null;
}
function saveConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(consent));
}
function applyConsent(consent: { analytics: boolean; marketing: boolean }) {
if (consent.analytics) {
document.body.classList.add('analytics-enabled');
} else {
document.body.classList.remove('analytics-enabled');
}
if (consent.marketing) {
document.body.classList.add('marketing-enabled');
} else {
document.body.classList.remove('marketing-enabled');
}
window.dispatchEvent(new CustomEvent('consent-updated', { detail: consent }));
}
async function logConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
try {
await fetch('/api/consent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: getSessionId(),
essential: consent.essential,
analytics: consent.analytics,
marketing: consent.marketing,
policyVersion: POLICY_VERSION,
}),
});
} catch (error) {
console.error('Failed to log consent:', error);
}
}
function openModal() {
const modal = document.getElementById('consent-preferences-modal');
const analyticsCheckbox = document.getElementById('consent-analytics') as HTMLInputElement;
const marketingCheckbox = document.getElementById('consent-marketing') as HTMLInputElement;
const existingConsent = getConsent();
if (existingConsent) {
analyticsCheckbox.checked = existingConsent.analytics;
marketingCheckbox.checked = existingConsent.marketing;
} else {
analyticsCheckbox.checked = false;
marketingCheckbox.checked = false;
}
modal?.classList.remove('hidden');
}
function closeModal() {
const modal = document.getElementById('consent-preferences-modal');
modal?.classList.add('hidden');
}
async function handleSave() {
const analyticsCheckbox = document.getElementById('consent-analytics') as HTMLInputElement;
const marketingCheckbox = document.getElementById('consent-marketing') as HTMLInputElement;
const consent = {
essential: true,
analytics: analyticsCheckbox.checked,
marketing: marketingCheckbox.checked,
};
saveConsent(consent);
await logConsent(consent);
applyConsent(consent);
closeModal();
}
document.addEventListener('DOMContentLoaded', () => {
const modal = document.getElementById('consent-preferences-modal');
const backdrop = document.getElementById('consent-modal-backdrop');
const saveBtn = document.getElementById('consent-save');
const closeBtn = document.getElementById('consent-close');
window.addEventListener('open-consent-preferences', openModal);
backdrop?.addEventListener('click', closeModal);
closeBtn?.addEventListener('click', closeModal);
saveBtn?.addEventListener('click', handleSave);
});
</script>

View File

@@ -0,0 +1,156 @@
---
interface Props {
showPreferences?: boolean;
}
const { showPreferences = false } = Astro.props;
---
<div id="cookie-banner" class={`fixed bottom-0 left-0 right-0 z-50 p-4 md:p-6 transition-transform duration-300 ${showPreferences ? 'translate-y-full' : 'translate-y-0'}`}>
<div class="max-w-4xl mx-auto bg-white rounded-lg shadow-2xl border border-gray-200 p-6">
<div class="flex flex-col md:flex-row gap-4 md:items-start md:justify-between">
<div class="flex-1">
<h2 class="text-lg font-semibold text-gray-900 mb-2">เราใช้คุกกี้</h2>
<p class="text-sm text-gray-600">
เราใช้คุกกี้เพื่อปรับปรุงประสบการณ์การใช้งานเว็บไซต์ โดยคลิกยอมรับเพื่อใช้งานคุกกี้ทุกประเภท หรือคลิกปรับแต่งเพื่อเลือกคุกกี้ที่ต้องการ
</p>
</div>
<div class="flex flex-col sm:flex-row gap-3 shrink-0">
<button
id="cookie-reject"
class="px-5 py-2.5 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400"
>
ปฏิเสธ
</button>
<button
id="cookie-customize"
class="px-5 py-2.5 text-sm font-medium text-green-700 bg-green-50 border border-green-200 rounded-lg hover:bg-green-100 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500"
>
ปรับแต่ง
</button>
<button
id="cookie-accept"
class="px-5 py-2.5 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500"
>
ยอมรับ
</button>
</div>
</div>
</div>
</div>
<script>
const POLICY_VERSION = '1.0';
const STORAGE_KEY = 'dealplustech_consent';
function generateSessionId(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getSessionId(): string {
let sessionId = localStorage.getItem('dealplustech_session');
if (!sessionId) {
sessionId = generateSessionId();
localStorage.setItem('dealplustech_session', sessionId);
}
return sessionId;
}
function getConsent(): { essential: boolean; analytics: boolean; marketing: boolean } | null {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
try {
return JSON.parse(stored);
} catch {
return null;
}
}
return null;
}
function saveConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(consent));
}
function hideBanner() {
const banner = document.getElementById('cookie-banner');
if (banner) {
banner.classList.add('translate-y-full');
setTimeout(() => banner.remove(), 300);
}
}
async function logConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
try {
await fetch('/api/consent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: getSessionId(),
essential: consent.essential,
analytics: consent.analytics,
marketing: consent.marketing,
policyVersion: POLICY_VERSION,
}),
});
} catch (error) {
console.error('Failed to log consent:', error);
}
}
function applyConsent(consent: { analytics: boolean; marketing: boolean }) {
if (consent.analytics) {
document.body.classList.add('analytics-enabled');
}
if (consent.marketing) {
document.body.classList.add('marketing-enabled');
}
window.dispatchEvent(new CustomEvent('consent-updated', { detail: consent }));
}
async function handleAccept() {
const consent = { essential: true, analytics: true, marketing: true };
saveConsent(consent);
await logConsent(consent);
applyConsent(consent);
hideBanner();
}
async function handleReject() {
const consent = { essential: true, analytics: false, marketing: false };
saveConsent(consent);
await logConsent(consent);
applyConsent(consent);
hideBanner();
}
function handleCustomize() {
window.dispatchEvent(new CustomEvent('open-consent-preferences'));
hideBanner();
}
document.addEventListener('DOMContentLoaded', () => {
const existingConsent = getConsent();
if (existingConsent) {
applyConsent(existingConsent);
return;
}
const banner = document.getElementById('cookie-banner');
if (!banner) return;
const acceptBtn = document.getElementById('cookie-accept');
const rejectBtn = document.getElementById('cookie-reject');
const customizeBtn = document.getElementById('cookie-customize');
acceptBtn?.addEventListener('click', handleAccept);
rejectBtn?.addEventListener('click', handleReject);
customizeBtn?.addEventListener('click', handleCustomize);
});
</script>

View File

@@ -1,33 +0,0 @@
'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>
);
}

View File

@@ -1,118 +0,0 @@
import Image from 'next/image';
import Link from 'next/link';
import { siteConfig, workHours, mainNavigation } from '@/data/site-config';
export default function Footer() {
return (
<footer className="bg-secondary-50 text-secondary-900">
{/* 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>
<Image
src="/images/2021/02/13523630950840.png"
alt="Deal Plus Tech"
width={150}
height={50}
className="h-10 w-auto mb-4"
/>
<p className="text-secondary-600 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-200 rounded-lg flex items-center justify-center text-secondary-700 hover:bg-primary-600 hover:text-white 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-200 rounded-lg flex items-center justify-center text-secondary-700 hover:bg-primary-600 hover:text-white 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-600"></h3>
<ul className="space-y-2">
{mainNavigation.slice(0, 5).map((item) => (
<li key={item.href}>
<Link href={item.href} className="text-secondary-600 hover:text-primary-600 transition-colors">
{item.label}
</Link>
</li>
))}
</ul>
</div>
{/* Contact Info */}
<div>
<h3 className="text-lg font-bold mb-4 text-primary-600"></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-600 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-600 hover:text-primary-600 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-600 hover:text-primary-600 text-sm">
{siteConfig.email}
</a>
</li>
</ul>
</div>
{/* Business Hours */}
<div>
<h3 className="text-lg font-bold mb-4 text-primary-600"></h3>
<ul className="space-y-2">
{workHours.map((item) => (
<li key={item.day} className="flex justify-between text-sm">
<span className="text-secondary-600">{item.day}</span>
<span className={item.isClosed ? 'text-red-500' : 'text-secondary-900 font-medium'}>
{item.hours}
</span>
</li>
))}
</ul>
</div>
</div>
</div>
{/* Bottom Bar */}
<div className="border-t border-secondary-200">
<div className="container mx-auto px-4 py-4">
<p className="text-center text-secondary-500 text-sm">
© {new Date().getFullYear()} {siteConfig.name}. .
</p>
</div>
</div>
</footer>
);
}

View File

@@ -1,201 +0,0 @@
'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);
return (
<header className="fixed top-0 left-0 right-0 z-50 bg-white shadow-md">
{/* 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">
<Image
src="/images/2021/02/13523630950840.png"
alt="Deal Plus Tech"
width={150}
height={50}
className="h-12 w-auto"
priority
/>
</Link>
{/* Desktop Navigation */}
<div className="hidden lg:flex items-center gap-1">
{mainNavigation.map((item) => (
<div
key={item.href}
className="relative group"
>
<Link
href={item.href}
className={cn(
"px-4 py-2 text-secondary-700 font-medium hover:text-primary-600 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 - CSS hover with invisible bridge */}
{item.children && (
<div className="absolute top-full left-0 pt-2 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50">
{/* Invisible bridge to prevent gap */}
<div className="absolute -top-2 left-0 right-0 h-2" />
<div className="min-w-[600px] bg-white shadow-xl rounded-lg py-4 border border-secondary-100">
<div className="grid grid-cols-2 gap-1 px-4">
{item.children.map((child) => (
<div key={child.href} className="relative group/sub">
<Link
href={child.href}
className="block px-3 py-2 text-secondary-700 hover:bg-primary-50 hover:text-primary-700 transition-colors rounded font-medium"
>
{child.label}
</Link>
{child.children && (
<div className="hidden group-hover/sub:block absolute left-full top-0 w-56 !bg-white shadow-xl rounded-lg py-2 border border-secondary-100 max-h-96 overflow-y-auto z-50">
{/* Invisible bridge to prevent gap */}
<div className="absolute -top-2 -bottom-2 -left-2 w-2" />
{child.children.map((subChild) => (
<Link
key={subChild.href}
href={subChild.href}
className="block px-4 py-2 text-secondary-600 hover:bg-primary-50 hover:text-primary-700 text-sm"
>
{subChild.label}
</Link>
))}
</div>
)}
</div>
))}
</div>
</div>
</div>
)}
</div>
))}
<Link href="/contact-us" className="btn-primary ml-4">
</Link>
</div>
{/* Mobile Menu Button */}
<button
className="lg:hidden text-secondary-900 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-200 max-h-[80vh] overflow-y-auto">
{mainNavigation.map((item) => (
<div key={item.href}>
{item.children ? (
<div className="border-b border-secondary-100">
<div className="px-4 py-3 font-semibold text-secondary-900 bg-secondary-50">
{item.label}
</div>
<div className="pl-4">
{item.children.map((child) => (
<div key={child.href}>
<Link
href={child.href}
className="block px-4 py-2 text-secondary-700 hover:text-primary-600 hover:bg-primary-50"
onClick={() => setMobileMenuOpen(false)}
>
{child.label}
</Link>
{child.children && (
<div className="pl-4 bg-secondary-50">
{child.children.map((subChild) => (
<Link
key={subChild.href}
href={subChild.href}
className="block px-4 py-2 text-secondary-600 hover:text-primary-600 text-sm"
onClick={() => setMobileMenuOpen(false)}
>
{subChild.label}
</Link>
))}
</div>
)}
</div>
))}
</div>
</div>
) : (
<Link
href={item.href}
className="block px-4 py-3 text-secondary-700 hover:text-primary-600 font-medium"
onClick={() => setMobileMenuOpen(false)}
>
{item.label}
</Link>
)}
</div>
))}
<div className="p-4">
<Link
href="/contact-us"
className="btn-primary block text-center"
onClick={() => setMobileMenuOpen(false)}
>
</Link>
</div>
</div>
)}
</nav>
</header>
);
}

View File

@@ -1,41 +0,0 @@
import { HTMLAttributes, forwardRef } from 'react';
import { cn } from '@/lib/utils';
interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
variant?: 'default' | 'primary' | 'success' | 'warning' | 'error';
size?: 'sm' | 'md' | 'lg';
}
const Badge = forwardRef<HTMLSpanElement, BadgeProps>(
({ className, variant = 'default', size = 'md', children, ...props }, ref) => {
return (
<span
ref={ref}
className={cn(
'inline-flex items-center font-medium rounded-full',
{
'bg-secondary-100 text-secondary-700': variant === 'default',
'bg-primary-100 text-primary-700': variant === 'primary',
'bg-green-100 text-green-700': variant === 'success',
'bg-yellow-100 text-yellow-700': variant === 'warning',
'bg-red-100 text-red-700': variant === 'error',
},
{
'px-2 py-0.5 text-xs': size === 'sm',
'px-3 py-1 text-sm': size === 'md',
'px-4 py-1.5 text-base': size === 'lg',
},
className
)}
{...props}
>
{children}
</span>
);
}
);
Badge.displayName = 'Badge';
export { Badge };
export type { BadgeProps };

View File

@@ -1,42 +0,0 @@
import { ButtonHTMLAttributes, forwardRef } from 'react';
import { cn } from '@/lib/utils';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
size?: 'sm' | 'md' | 'lg';
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant = 'primary', size = 'md', children, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(
'inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:pointer-events-none disabled:opacity-50',
// Variants
{
'bg-primary-600 text-white hover:bg-primary-700 active:bg-primary-800': variant === 'primary',
'bg-secondary-100 text-secondary-900 hover:bg-secondary-200': variant === 'secondary',
'border-2 border-primary-600 text-primary-600 hover:bg-primary-50': variant === 'outline',
'text-secondary-600 hover:bg-secondary-100': variant === 'ghost',
},
// Sizes
{
'px-3 py-1.5 text-sm rounded': size === 'sm',
'px-4 py-2 text-base rounded-md': size === 'md',
'px-6 py-3 text-lg rounded-lg': size === 'lg',
},
className
)}
{...props}
>
{children}
</button>
);
}
);
Button.displayName = 'Button';
export { Button };
export type { ButtonProps };

View File

@@ -1,63 +0,0 @@
import { HTMLAttributes, forwardRef } from 'react';
import { cn } from '@/lib/utils';
interface CardProps extends HTMLAttributes<HTMLDivElement> {
variant?: 'default' | 'bordered' | 'elevated';
}
const Card = forwardRef<HTMLDivElement, CardProps>(
({ className, variant = 'default', children, ...props }, ref) => {
return (
<div
ref={ref}
className={cn(
'bg-white rounded-xl overflow-hidden',
{
'shadow-sm': variant === 'default',
'border border-secondary-200': variant === 'bordered',
'shadow-lg': variant === 'elevated',
},
className
)}
{...props}
>
{children}
</div>
);
}
);
Card.displayName = 'Card';
const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, children, ...props }, ref) => (
<div ref={ref} className={cn('p-4 border-b border-secondary-100', className)} {...props}>
{children}
</div>
)
);
CardHeader.displayName = 'CardHeader';
const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, children, ...props }, ref) => (
<div ref={ref} className={cn('p-4', className)} {...props}>
{children}
</div>
)
);
CardContent.displayName = 'CardContent';
const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, children, ...props }, ref) => (
<div ref={ref} className={cn('p-4 border-t border-secondary-100 bg-secondary-50', className)} {...props}>
{children}
</div>
)
);
CardFooter.displayName = 'CardFooter';
export { Card, CardHeader, CardContent, CardFooter };
export type { CardProps };

View File

@@ -1,11 +0,0 @@
// UI Components - Reusable components for Deal Plus Tech website
// These components follow the project's design system using Tailwind CSS
export { Button } from './Button';
export type { ButtonProps } from './Button';
export { Card, CardHeader, CardContent, CardFooter } from './Card';
export type { CardProps } from './Card';
export { Badge } from './Badge';
export type { BadgeProps } from './Badge';

View File

@@ -1,94 +0,0 @@
# DATA LAYER - Product Catalog & Site Configuration
**Generated:** 2026-03-01
## OVERVIEW
Centralized data layer for product catalog (~150KB total). Contains all product information, specifications, pricing tables, and site configuration in TypeScript.
## FILES
| File | Size | Purpose |
|------|------|---------|
| `site-config.ts` | ~149KB | Products, navigation, portfolio, company info |
| `product-tables.ts` | ~33KB | Specification tables for products |
## STRUCTURE
### site-config.ts
```typescript
// Core exports
export const siteConfig: SiteConfig // Company info, contact
export const workHours: WorkHours[] // Business hours
export const productCategories: ProductCategory[] // All products (~20+)
export const mainNavigation: NavItem[] // Header nav
export const portfolioProjects: PortfolioProject[] // Portfolio items
```
### ProductCategory Interface
```typescript
interface ProductCategory {
id: string; // kebab-case ID (e.g., 'ppr-elephant')
name: string; // Thai name
nameEn: string; // English name
slug: string; // URL slug (Thai)
href: string; // Full path with trailing slash
image: string; // Image path from /public
description: string; // Full description (Thai)
shortDescription?: string;
keywords?: string[]; // SEO keywords
seoContent?: string; // Long-form SEO content
specifications?: ProductSpecification[];
features?: string[];
applications?: string[];
certifications?: string[];
faq?: FAQItem[];
schemaData?: {...}; // Schema.org structured data
relatedProductIds?: string[];
productTables?: ProductTable[]; // From product-tables.ts
}
```
## PRODUCT CATEGORIES
| ID | Thai Name | Type |
|----|-----------|------|
| `ppr-elephant` | ท่อพีพีอาร์ตราช้าง | PPR Pipe |
| `thai-ppr` | ท่อ PPR Thai PPR | PPR Pipe |
| `poloplast` | ท่อ PP-R/PP-RCT POLOPLAST | Premium PPR |
| `ppr-welder` | เครื่องเชื่อมท่อพีพีอาร์ | Equipment |
| `hdpe` | ท่อ HDPE | HDPE Pipe |
| `hdpe-welder` | เครื่องเชื่อม HDPE | Equipment |
| `upvc` | ท่อ uPVC | uPVC Pipe |
| `pvc` | ท่อและข้อต่อ PVC | PVC Pipe |
| `syler` | ท่อไซเลอร์ | Fire protection |
| `xylent` | ท่อระบายน้ำ 3 ชั้น ไซเลนท์ | Drainage |
| ... | ... | ... |
## CONVENTIONS
**Adding a new product**:
1. Add to `productCategories[]` array
2. Create unique `id` (kebab-case)
3. Add Thai `slug` for URL
4. Include `seoContent` for SEO pages
5. Link `productTables` if spec tables exist
6. Add `relatedProductIds` for cross-selling
**Product images**: Store in `/public/images/YYYY/MM/`
**URLs**: Thai with trailing slash: `/ท่อพีพีอาร์ตราช้าง/`
## ANTI-PATTERNS
- **DO NOT** import entire file in client components - it's 149KB
- **DO NOT** hardcode product IDs - use constants
- **DO NOT** edit `product-tables.ts` manually without checking all references
## NOTES
- File is large but tree-shakeable for unused products
- `portfolioProjects` also defined here
- SEO keywords array should include both Thai and English terms

View File

@@ -1,687 +0,0 @@
import { ProductTable } from '@/types';
// DUKELARRSEN Product Tables
export const dukelarrsenTables: ProductTable[] = [
{
tableName: 'Rigid Coupling DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Bolt Size', 'Dimensions A (mm)', 'Dimensions B (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['25', '1', '33.7', '2-M10 x 45', '57', '97', '300', 'FM UL'],
['32', '1-1/4', '42.4', '2-M10 x 45', '67', '107.5', '300', 'FM UL'],
['40', '1-1/2', '48.3', '2-M10 x 45', '72', '114', '300', 'FM UL'],
['50', '2', '60.3', '2-M10 x 55', '85', '137', '300', 'FM UL'],
['65', '2-1/2', '73.0', '2-M10 x 55', '98', '139', '300', 'FM UL'],
['65', '2-1/2', '76.1', '2-M10 x 55', '100', '139', '300', 'FM UL'],
['80', '3', '88.9', '2-M10 x 55', '114', '160', '300', 'FM UL'],
['100', '4', '114.3', '2-M12 x 65', '147.2', '193', '300', 'FM UL'],
['125', '5', '139.7', '2-M12 x 75', '170', '222', '300', 'FM UL'],
['125', '5', '141.3', '2-M12 x 75', '170', '222', '300', 'FM UL'],
['150', '6', '168.3', '2-M12 x 75', '203', '248', '300', 'FM UL'],
['150', '6', '165.1', '2-M12 x 75', '205', '254', '300', 'FM UL'],
['200', '8', '219.1', '2-M16 x 85', '257', '330', '300', 'FM UL'],
['250', '10', '273.0', '2-M20 x 120', '328', '420', '300', 'FM UL'],
['300', '12', '323.9', '2-M20 x 140', '380', '454', '300', 'FM UL'],
],
},
{
tableName: 'Flexible Coupling DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Bolt Size', 'Dimensions A (mm)', 'Dimensions B (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['25', '1', '33.7', '2-M10 x 45', '57', '97', '300', 'FM UL'],
['32', '1-1/4', '42.4', '2-M10 x 45', '67', '107.5', '300', 'FM UL'],
['40', '1-1/2', '48.3', '2-M10 x 45', '72', '114', '300', 'FM UL'],
['50', '2', '60.3', '2-M10 x 55', '85', '137', '300', 'FM UL'],
['65', '2-1/2', '73.0', '2-M10 x 55', '98', '139', '300', 'FM UL'],
['65', '2-1/2', '76.1', '2-M10 x 55', '100', '139', '300', 'FM UL'],
['80', '3', '88.9', '2-M10 x 55', '114', '160', '300', 'FM UL'],
['100', '4', '114.3', '2-M12 x 66', '147.2', '193', '300', 'FM UL'],
['125', '5', '139.7', '2-M12 x 75', '170', '222', '300', 'FM UL'],
['125', '5', '141.3', '2-M12 x 75', '170', '222', '300', 'FM UL'],
['150', '6', '168.3', '2-M12 x 75', '203', '248', '300', 'FM UL'],
['150', '6', '165.1', '2-M12 x 75', '205', '254', '300', 'FM UL'],
['200', '8', '219.1', '2-M16 x 85', '257', '330', '300', 'FM UL'],
['250', '10', '273.0', '2-M20 x 120', '328', '420', '300', 'FM UL'],
['300', '12', '323.9', '2-M20 x 140', '380', '454', '300', 'FM UL'],
],
},
{
tableName: 'Reducing Flexible Coupling DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Bolt Size', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['50 x 40', '2 x 1-1/2', '60.3 x 48.3', '2-M10 x 55', '300', 'FM UL'],
['65 x 50', '2-1/2 x 2', '73 x 60.3', '2-M10 x 55', '300', 'FM UL'],
['65 x 50', '2-1/2 x 2', '76.1 x 60.3', '2-M10 x 55', '300', 'FM UL'],
['80 x 25', '3 x 1', '88.9 x 33.7', '2-M10 x 55', '300', 'FM UL'],
['80 x 50', '3 x 2', '88.9 x 60.3', '2-M10 x 55', '300', 'FM UL'],
['80 x 65', '3 x 2-1/2', '88.9 x 76.1', '2-M10 x 55', '300', 'FM UL'],
['100 x 25', '4 x 1', '114.3 x 33.7', '2-M12 x 65', '300', 'FM UL'],
['100 x 50', '4 x 2', '114.3 x 60.3', '2-M12 x 65', '300', 'FM UL'],
['100 x 65', '4 x 2-1/2', '114.3 x 73.0', '2-M12 x 65', '300', 'FM UL'],
['100 x 65', '4 x 2-1/2', '114.3 x 76.1', '2-M12 x 65', '300', 'FM UL'],
['100 x 80', '4 x 3', '114.3 x 88.9', '2-M12 x 65', '300', 'FM UL'],
['150 x 80', '6 x 3', '168.3 x 88.9', '2-M12 x 75', '300', 'FM UL'],
['150 x 100', '6 x 4', '168.3 x 114.3', '2-M12 x 75', '300', 'FM UL'],
],
},
{
tableName: 'Flange PN16 Grooved DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Bolt Size', 'Dimensions D (mm)', 'Dimensions D1 (mm)', 'Dimensions D2 (mm)', 't (mm)', 'Hole', 'Angle', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['50', '2', '60.3', '2-M10 x 70', '220', '165', '125', '23', '4-Ø18', '30°', '300', 'FM UL'],
['65', '2-1/2', '73.0', '2-M10 x 70', '235', '185', '145', '23', '4-Ø18', '30°', '300', 'FM UL'],
['65', '2-1/2', '76.1', '2-M10 x 70', '235', '185', '145', '23', '4-Ø18', '30°', '300', 'FM UL'],
['80', '3', '88.9', '2-M10 x 70', '255', '195', '160', '23', '4-Ø18', '30°', '300', 'FM UL'],
['100', '4', '114.3', '2-M12 x 70', '279', '224', '180', '23', '4-Ø18', '30°', '300', 'FM UL'],
['125', '5', '139.7', '2-M12 x 70', '320', '250', '216', '24', '8-Ø18', '30°', '300', 'FM UL'],
['125', '5', '141.3', '2-M12 x 70', '320', '250', '216', '24', '8-Ø18', '30°', '300', 'FM UL'],
['150', '6', '165.1', '2-M12 x 70', '346', '280', '240', '24', '8-Ø22', '30°', '300', 'FM UL'],
['150', '6', '168.3', '2-M12 x 70', '346', '280', '240', '24', '8-Ø22', '30°', '300', 'FM UL'],
['200', '8', '219.1', '2-M12 x 80', '414', '340', '295', '28', '8-Ø22', '30°', '300', 'FM UL'],
['250', '10', '273.0', '2-M12 x 80', '480', '405', '355', '30', '12-Ø26', '50°', '300', 'FM UL'],
['300', '12', '323.9', '2-M12 x 80', '530', '460', '410', '32', '12-Ø26', '30°', '300', 'FM UL'],
],
},
{
tableName: 'Elbow 90° Grooved DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Dimensions (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['25', '1', '33.7', '57', '300', 'FM UL'],
['32', '1-1/4', '42.4', '67', '300', 'FM UL'],
['40', '1-1/2', '48.3', '76', '300', 'FM UL'],
['50', '2', '60.3', '89', '300', 'FM UL'],
['65', '2-1/2', '73.0', '102', '300', 'FM UL'],
['65', '2-1/2', '76.1', '102', '300', 'FM UL'],
['80', '3', '88.9', '114', '300', 'FM UL'],
['100', '4', '114.3', '140', '300', 'FM UL'],
['125', '5', '141.3', '159', '300', 'FM UL'],
['125', '5', '139.7', '159', '300', 'FM UL'],
['150', '6', '168.3', '178', '300', 'FM UL'],
['150', '6', '165.1', '178', '300', 'FM UL'],
['200', '8', '219.1', '229', '300', 'FM UL'],
['250', '10', '273.0', '279', '300', 'FM UL'],
['300', '12', '323.9', '330', '300', 'FM UL'],
],
},
{
tableName: 'Tee Grooved DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Dimensions (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['25', '1', '33.7', '57', '300', 'FM UL'],
['32', '1-1/4', '42.4', '67', '300', 'FM UL'],
['40', '1-1/2', '48.3', '70', '300', 'FM UL'],
['50', '2', '60.3', '70', '300', 'FM UL'],
['65', '2-1/2', '73.0', '86', '300', 'FM UL'],
['65', '2-1/2', '76.1', '86', '300', 'FM UL'],
['80', '3', '88.9', '95', '300', 'FM UL'],
['100', '4', '114.3', '102', '300', 'FM UL'],
['125', '5', '139.7', '122', '300', 'FM UL'],
['125', '5', '141.3', '122', '300', 'FM UL'],
['150', '6', '168.3', '140', '300', 'FM UL'],
['150', '6', '165.1', '140', '300', 'FM UL'],
['200', '8', '219.1', '178', '300', 'FM UL'],
['250', '10', '273.0', '216', '300', 'FM UL'],
['300', '12', '323.9', '254', '300', 'FM UL'],
],
},
{
tableName: 'Reducer (Concentric) Grooved DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['32 x 25', '1-1/4 x 1', '42.4 x 33.7', '300', 'FM UL'],
['40 x 25', '1-1/2 x 1', '48.3 x 33.7', '300', 'FM UL'],
['40 x 32', '1-1/2 x 1-1/4', '48.3 x 42.4', '300', 'FM UL'],
['50 x 25', '2 x 1', '60.3 x 33.7', '300', 'FM UL'],
['50 x 32', '2 x 1-1/4', '60.3 x 42.4', '300', 'FM UL'],
['50 x 40', '2 x 1-1/2', '60.3 x 48.3', '300', 'FM UL'],
['65 x 25', '2-1/2 x 1', '73.0 x 33.7', '300', 'FM UL'],
['65 x 25', '2-1/2 x 1', '76.1 x 33.7', '300', 'FM UL'],
['65 x 32', '2-1/2 x 1-1/4', '73.0 x 42.4', '300', 'FM UL'],
['65 x 32', '2-1/2 x 1-1/4', '76.1 x 42.4', '300', 'FM UL'],
['65 x 40', '2-1/2 x 1-1/2', '73.0 x 48.3', '300', 'FM UL'],
['65 x 40', '2-1/2 x 1-1/2', '76.1 x 48.3', '300', 'FM UL'],
['65 x 50', '2-1/2 x 2', '73.0 x 60.3', '300', 'FM UL'],
['65 x 50', '2-1/2 x 2', '76.1 x 60.3', '300', 'FM UL'],
['80 x 25', '3 x 1', '88.9 x 33.7', '300', 'FM UL'],
['80 x 32', '3 x 1-1/4', '88.9 x 42.4', '300', 'FM UL'],
['80 x 40', '3 x 1-1/2', '88.9 x 48.3', '300', 'FM UL'],
['80 x 50', '3 x 2', '88.9 x 60.3', '300', 'FM UL'],
['80 x 65', '3 x 2-1/2', '88.9 x 73.0', '300', 'FM UL'],
['80 x 65', '3 x 2-1/2', '88.9 x 76.1', '300', 'FM UL'],
['100 x 32', '4 x 1-1/4', '114.3 x 42.4', '300', 'FM UL'],
['100 x 40', '4 x 1-1/2', '114.3 x 48.3', '300', 'FM UL'],
['100 x 50', '4 x 2', '114.3 x 60.3', '300', 'FM UL'],
['100 x 65', '4 x 2-1/2', '114.3 x 73.0', '300', 'FM UL'],
['100 x 65', '4 x 2-1/2', '114.3 x 76.1', '300', 'FM UL'],
['100 x 80', '4 x 3', '114.3 x 88.9', '300', 'FM UL'],
['125 x 50', '5 x 2', '139.7 x 60.3', '300', 'FM UL'],
['125 x 65', '5 x 2-1/2', '139.7 x 73.0', '300', 'FM UL'],
['125 x 80', '5 x 3', '139.7 x 88.9', '300', 'FM UL'],
['125 x 100', '5 x 4', '139.7 x 114.3', '300', 'FM UL'],
['150 x 65', '6 x 2-1/2', '165.1 x 73.0', '300', 'FM UL'],
['150 x 80', '6 x 3', '165.1 x 88.9', '300', 'FM UL'],
['150 x 80', '6 x 3', '168.3 x 88.9', '300', 'FM UL'],
['150 x 100', '6 x 4', '165.1 x 114.3', '300', 'FM UL'],
['150 x 100', '6 x 4', '168.3 x 114.3', '300', 'FM UL'],
['200 x 100', '8 x 4', '219.1 x 114.3', '300', 'FM UL'],
['200 x 125', '8 x 5', '219.1 x 139.7', '300', 'FM UL'],
['200 x 150', '8 x 6', '219.1 x 168.3', '300', 'FM UL'],
['200 x 150', '8 x 6', '219.1 x 165.1', '300', 'FM UL'],
['250 x 150', '10 x 6', '273.0 x 165.1', '300', 'FM UL'],
['250 x 200', '10 x 8', '273.0 x 219.1', '300', 'FM UL'],
],
},
{
tableName: 'Cap Grooved DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Dimensions (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['25', '1', '33.7', '23.8', '300', 'FM UL'],
['32', '1-1/4', '42.4', '23.8', '300', 'FM UL'],
['40', '1-1/2', '48.3', '23.8', '300', 'FM UL'],
['50', '2', '60.3', '23.8', '300', 'FM UL'],
['65', '2-1/2', '73.0', '23.8', '300', 'FM UL'],
['65', '2-1/2', '76.1', '23.8', '300', 'FM UL'],
['80', '3', '88.9', '23.8', '300', 'FM UL'],
['100', '4', '114.3', '25.4', '300', 'FM UL'],
['125', '5', '139.7', '25.4', '300', 'FM UL'],
['150', '6', '168.3', '25.4', '300', 'FM UL'],
['150', '6', '165.1', '25.4', '300', 'FM UL'],
['200', '8', '219.1', '32', '300', 'FM UL'],
['250', '10', '273.0', '32', '300', 'FM UL'],
['300', '12', '323.9', '32', '300', 'FM UL'],
],
},
{
tableName: 'Mechanical Tee (Grooved) DUKELARRSEN',
headers: ['Nominal Size (mm)', 'Nominal Size (in)', 'Pipe OD (mm)', 'Bolt Size', 'Dimensions A (mm)', 'Dimensions B (mm)', 'Dimensions C (mm)', 'Dimensions L (mm)', 'Working Pressure (PSI)', 'Certificate'],
rows: [
['50 x 32', '2 x 1-1/4', '60.3 x 42.4', '2-M10 x 70', '46', '75', '120', '70', '300', 'FM UL'],
['50 x 40', '2 x 1-1/2', '60.3 x 48.3', '2-M10 x 70', '46', '75/120', '70', '69', '300', 'FM UL'],
['65 x 32', '2-1/2 x 1-1/4', '73.0 x 42.4', '2-M10 x 70', '52', '93/137', '78', '77', '300', 'FM UL'],
['65 x 40', '2-1/2 x 1-1/2', '73.0 x 48.3', '2-M10 x 70', '52', '93/137', '78', '63', '300', 'FM UL'],
['65 x 50', '2-1/2 x 2', '73.0 x 60.3', '2-M10 x 70', '52', '93/137', '78', '83', '300', 'FM UL'],
['65 x 40', '2-1/2 x 1-1/2', '76.1 x 48.3', '2-M10 x 70', '52', '93/137', '78', '83', '300', 'FM UL'],
['80 x 40', '3 x 1-1/2', '88.9 x 48.3', '2-M10 x 70', '46', '114/152', '85', '78', '300', 'FM UL'],
['80 x 50', '3 x 2', '88.9 x 60.3', '2-M10 x 70', '46', '114/152', '85', '93', '300', 'FM UL'],
['80 x 65', '3 x 2-1/2', '88.9 x 76.1', '2-M10 x 70', '64', '140', '180', '99', '300', 'FM UL'],
['100 x 40', '4 x 1-1/2', '114.3 x 48.3', '2-M12 x 75', '46', '140/180', '97', '83', '300', 'FM UL'],
['100 x 50', '4 x 2', '114.3 x 60.3', '2-M12 x 75', '64', '140', '180', '99', '300', 'FM UL'],
['100 x 65', '4 x 2-1/2', '114.3 x 73.0', '2-M12 x 75', '64', '168', '220', '99', '300', 'FM UL'],
['100 x 80', '4 x 3', '114.3 x 88.9', '2-M12 x 75', '64', '168', '220', '113', '300', 'FM UL'],
['125 x 65', '5 x 2-1/2', '139.7 x 73.0', '2-M12 x 75', '70', '168', '220', '122', '300', 'FM UL'],
['125 x 80', '5 x 3', '139.7 x 88.9', '2-M12 x 75', '70', '194/248', '130', '83', '300', 'FM UL'],
['125 x 100', '5 x 4', '139.7 x 114.3', '2-M12 x 75', '70', '194/248', '130', '98', '300', 'FM UL'],
['150 x 65', '6 x 2-1/2', '168.3 x 73.0', '2-M12 x 75', '70', '198/248', '131', '122', '300', 'FM UL'],
['150 x 80', '6 x 3', '168.3 x 88.9', '2-M12 x 75', '70', '198/248', '131', '125', '300', 'FM UL'],
['150 x 100', '6 x 4', '168.3 x 114.3', '2-M12 x 75', '70', '198/248', '131', '139', '300', 'FM UL'],
['150 x 80', '6 x 3', '165.1 x 88.9', '2-M12 x 75', '70', '250/311', '152', '130', '300', 'FM UL'],
['150 x 100', '6 x 4', '165.1 x 114.3', '2-M12 x 75', '89', '250/311', '152', '137', '300', 'FM UL'],
['200 x 100', '8 x 4', '219.1 x 114.3', '2-M16 x 100', '114', '250/321', '153', '162', '300', 'FM UL'],
],
},
// Additional tables would be added here for full DUKELARRSEN data
// Including: Elbow 22.5°, Elbow 45°, Eccentric Reducer, Tee Reducing, Cross, Cross Reducing, Cap with Eccentric Hole, Mechanical Tee Threaded, Mechanical Tee U-Bolt
];
// =====================================================
// PIPE HANGER TABLES
// =====================================================
// Clevis Hanger Tables
export const clevisHangerTables: ProductTable[] = [
{
tableName: 'Clevis Hanger (เหล็ก)',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'Upper มม.', 'Lower มม.', 'ขนาดสตัด Rod Size', 'ขนาดบรรจุ/ถุง Units/Bag'],
rows: [
['1', '1/2″', '15-21', '2.0×25', '3/8″', '100'],
['2', '3/4″', '20-27', '2.0×25', '3/8″', '100'],
['3', '1″', '25-34', '2.0×25', '3/8″', '100'],
['4', '1-1/4″', '32-42', '2.5×25', '3/8″', '100'],
['5', '1-1/2″', '40-48', '2.5×25', '3/8″', '100'],
['6', '2″', '50-60', '2.5×25', '3/8″', '100'],
['7', '2-1/2″', '65-76', '2.5×30', '3/8″', '50'],
['8', '3″', '80-89', '3.0×30', '3/8″', '50'],
['9', '4″', '100-114', '3.0×35', '1/2″', '25'],
],
},
{
tableName: 'Clevis Hanger Stainless Steel (สแตนเลส)',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'Upper มม.', 'Lower มม.', 'ขนาดสตัด Rod Size', 'ขนาดบรรจุ/ถุง Units/Bag'],
rows: [
['1', '1/2″', '15-21', '2.0×25', '3/8″', '100'],
['2', '3/4″', '20-27', '2.0×25', '3/8″', '100'],
['3', '1″', '25-34', '2.0×25', '3/8″', '100'],
['4', '1-1/4″', '32-42', '2.5×25', '3/8″', '100'],
['5', '1-1/2″', '40-48', '2.5×25', '3/8″', '100'],
['6', '2″', '50-60', '2.5×25', '3/8″', '100'],
['7', '2-1/2″', '65-76', '2.5×30', '3/8″', '50'],
['8', '3″', '80-89', '3.0×30', '3/8″', '50'],
['9', '4″', '100-114', '3.0×35', '1/2″', '25'],
['10', '5″', '125-140', '3.0×40', '1/2″', '20'],
],
},
];
// Split Ring Hanger Tables
export const splitRingHangerTables: ProductTable[] = [
{
tableName: 'Split Ring Hanger (เหล็ก) - Size 15-100mm',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'A มม.', 'B มม.', 'C มม.', 'D มม.', 'ขนาดสตัด Rod Size'],
rows: [
['1', '1/2″', '15', '42', '32', '8', '8', 'M8'],
['2', '3/4″', '20', '47', '35', '8', '9', 'M8'],
['3', '1″', '25', '56', '42', '8', '11', 'M8'],
['4', '1-1/4″', '32', '64', '48', '10', '12', 'M10'],
['5', '1-1/2″', '40', '73', '54', '10', '13', 'M10'],
['6', '2″', '50', '84', '62', '10', '15', 'M10'],
['7', '2-1/2″', '65', '101', '73', '12', '17', 'M12'],
['8', '3″', '80', '117', '85', '12', '19', 'M12'],
['9', '4″', '100', '141', '100', '14', '22', 'M14'],
],
},
{
tableName: 'Split Ring Hanger (เหล็ก) - Size 125-200mm',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'A มม.', 'B มม.', 'C มม.', 'D มม.', 'ขนาดสตัด Rod Size'],
rows: [
['1', '5″', '125', '170', '120', '16', '25', 'M16'],
['2', '6″', '150', '198', '138', '16', '28', 'M16'],
['3', '8″', '200', '253', '175', '20', '32', 'M20'],
],
},
{
tableName: 'Split Ring Hanger Stainless Steel (สแตนเลส)',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'A มม.', 'B มม.', 'C มม.', 'D มม.', 'ขนาดสตัด Rod Size'],
rows: [
['1', '1/2″', '15', '42', '32', '8', '8', 'M8'],
['2', '3/4″', '20', '47', '35', '8', '9', 'M8'],
['3', '1″', '25', '56', '42', '8', '11', 'M8'],
['4', '1-1/4″', '32', '64', '48', '10', '12', 'M10'],
['5', '1-1/2″', '40', '73', '54', '10', '13', 'M10'],
['6', '2″', '50', '84', '62', '10', '15', 'M10'],
['7', '2-1/2″', '65', '101', '73', '12', '17', 'M12'],
['8', '3″', '80', '117', '85', '12', '19', 'M12'],
['9', '4″', '100', '141', '100', '14', '22', 'M14'],
['10', '5″', '125', '170', '120', '16', '25', 'M16'],
['11', '6″', '150', '198', '138', '16', '28', 'M16'],
],
},
];
// Beam Clamp Tables
export const beamClampTables: ProductTable[] = [
{
tableName: 'Beam Clamp Type 1 (ฟันเดี่ยว)',
headers: ['No.', 'ขนาด (Size)', 'A มม.', 'B มม.', 'C มม.', 'D มม.', 'ขนาดสตัด Rod Size', 'ขนาดบรรจุ/ถุง Units/Bag'],
rows: [
['1', 'สตัด #1', '52', '41', '31', '12', 'M8', '50'],
['2', 'สตัด #2', '65', '54', '31', '12', 'M8', '50'],
['3', 'สตัด #3', '90', '79', '31', '12', 'M8', '50'],
['4', 'สตัด #4', '110', '99', '31', '12', 'M8', '50'],
],
},
{
tableName: 'Beam Clamp Type C (ฟันคู่)',
headers: ['No.', 'ขนาด (Size)', 'A มม.', 'B มม.', 'C มม.', 'D มม.', 'ขนาดสตัด Rod Size', 'ขนาดบรรจุ/ถุง Units/Bag'],
rows: [
['1', 'สตัด #2C', '65', '54', '31', '12', 'M8', '50'],
['2', 'สตัด #3C', '90', '79', '31', '12', 'M8', '50'],
['3', 'สตัด #4C', '110', '99', '31', '12', 'M8', '50'],
],
},
{
tableName: 'Beam Clamp Accessories',
headers: ['No.', 'รายการ', 'รายละเอียด', 'ขนาดบรรจุ/ถุง Units/Bag'],
rows: [
['1', 'สลักเกลียว สตัด', 'M8×30mm', '200'],
['2', 'สลักเกลียว สตัด', 'M10×30mm', '200'],
['3', 'สลักเกลียว สตัด', 'M12×30mm', '100'],
['4', 'น็อตตัวหนู', 'M8', '200'],
['5', 'น็อตตัวหนู', 'M10', '200'],
['6', 'น็อตตัวหนู', 'M12', '100'],
['7', 'แหวนรอง', 'M8', '500'],
['8', 'แหวนรอง', 'M10', '500'],
],
},
];
// Band Hanger Tables
export const bandHangerTables: ProductTable[] = [
{
tableName: 'Band Hanger (แคล้มหยดน้ำ)',
headers: ['No.', 'ขนาด (Size) นิ้ว', 'ขนาด (Size) มม.', 'A มม.', 'B มม.', 'ขนาดสตัด Rod Size'],
rows: [
['1', '1/2″', '15', '30', '25', 'M8'],
['2', '3/4″', '20', '35', '28', 'M8'],
['3', '1″', '25', '42', '32', 'M8'],
['4', '1-1/4″', '32', '50', '38', 'M10'],
['5', '1-1/2″', '40', '58', '42', 'M10'],
['6', '2″', '50', '70', '50', 'M10'],
['7', '2-1/2″', '65', '85', '60', 'M12'],
['8', '3″', '80', '100', '70', 'M12'],
['9', '4″', '100', '125', '85', 'M14'],
['10', '5″', '125', '150', '100', 'M16'],
['11', '6″', '150', '175', '115', 'M16'],
['12', '8″', '200', '225', '140', 'M20'],
],
},
];
// Combined Pipe Hanger Tables for product pages
export const pipeHangerTables: ProductTable[] = [
...clevisHangerTables,
...splitRingHangerTables,
...beamClampTables,
...bandHangerTables,
];
// =====================================================
// PPR WELDING MACHINE TABLES
// =====================================================
export const pprWelderTables: ProductTable[] = [
{
tableName: 'ราคาเครื่องเชื่อมท่อพีพีอาร์ (PPR Welding Machine Price List)',
headers: ['No.', 'รายการ', 'ราคา (บาท)'],
rows: [
// Welding Machines
['1', 'เครื่องเชื่อมท่อ PPR ขนาด 20-32mm 800W', '3,500'],
['2', 'เครื่องเชื่อมท่อ PPR ขนาด 20-63mm 1500W', '5,800'],
['3', 'เครื่องเชื่อมท่อ PPR ขนาด 20-75mm 1800W', '7,200'],
['4', 'เครื่องเชื่อมท่อ PPR ขนาด 20-90mm 2000W', '9,500'],
['5', 'เครื่องเชื่อมท่อ PPR ขนาด 20-110mm 2200W', '12,000'],
// Aiguille (Saddle Drill)
['6', 'สว่านเจาะท่อ Aiguille 20mm', '1,200'],
['7', 'สว่านเจาะท่อ Aiguille 25mm', '1,300'],
['8', 'สว่านเจาะท่อ Aiguille 32mm', '1,500'],
['9', 'สว่านเจาะท่อ Aiguille 40mm', '1,800'],
['10', 'สว่านเจาะท่อ Aiguille 50mm', '2,100'],
['11', 'สว่านเจาะท่อ Aiguille 63mm', '2,500'],
// Welding Saddle Mould
['12', 'หัวเชื่อมแบบ Saddle 20mm', '350'],
['13', 'หัวเชื่อมแบบ Saddle 25mm', '380'],
['14', 'หัวเชื่อมแบบ Saddle 32mm', '420'],
['15', 'หัวเชื่อมแบบ Saddle 40mm', '480'],
['16', 'หัวเชื่อมแบบ Saddle 50mm', '550'],
['17', 'หัวเชื่อมแบบ Saddle 63mm', '650'],
// Repairing Stick Mould
['18', 'แท่งซ่อม Repairing Stick 20mm', '280'],
['19', 'แท่งซ่อม Repairing Stick 25mm', '300'],
['20', 'แท่งซ่อม Repairing Stick 32mm', '340'],
['21', 'แท่งซ่อม Repairing Stick 40mm', '380'],
['22', 'แท่งซ่อม Repairing Stick 50mm', '420'],
['23', 'แท่งซ่อม Repairing Stick 63mm', '500'],
// Welding Mould - 20mm
['24', 'หัวเชื่อม Welding Mould 20mm (คู่)', '180'],
// Welding Mould - 25mm
['25', 'หัวเชื่อม Welding Mould 25mm (คู่)', '190'],
// Welding Mould - 32mm
['26', 'หัวเชื่อม Welding Mould 32mm (คู่)', '210'],
// Welding Mould - 40mm
['27', 'หัวเชื่อม Welding Mould 40mm (คู่)', '240'],
// Welding Mould - 50mm
['28', 'หัวเชื่อม Welding Mould 50mm (คู่)', '280'],
// Welding Mould - 63mm
['29', 'หัวเชื่อม Welding Mould 63mm (คู่)', '340'],
// Welding Mould - 75mm
['30', 'หัวเชื่อม Welding Mould 75mm (คู่)', '420'],
// Welding Mould - 90mm
['31', 'หัวเชื่อม Welding Mould 90mm (คู่)', '520'],
// Welding Mould - 110mm
['32', 'หัวเชื่อม Welding Mould 110mm (คู่)', '680'],
// Additional sizes
['33', 'หัวเชื่อม Welding Mould 125mm (คู่)', '850'],
['34', 'หัวเชื่อม Welding Mould 160mm (คู่)', '1,200'],
['35', 'เครื่องเชื่อม Butt Fusion 63-160mm', '45,000'],
['36', 'เครื่องเชื่อม Butt Fusion 160-315mm', '85,000'],
['37', 'เครื่องเชื่อม Butt Fusion 315-630mm', '150,000'],
],
},
];
// =====================================================
// PVC PIPE TABLES
// =====================================================
export const pvcTables: ProductTable[] = [
{
tableName: 'คุณสมบัติท่อ PVC ลักษณะการใช้งานและกายภาพทั่วไป',
headers: ['คุณสมบัติ', 'รายละเอียด'],
rows: [
['การใช้งาน', 'ท่อน้ำดี, ท่อน้ำเสีย'],
['สี', 'ฟ้า เหลือง เทา ขาว'],
['การติดตั้ง', 'ใช้น้ำยาประสานท่อในการประสานกัน'],
['อุณหภูมิที่เหมาะสม', '3-50 องศาเซลเซียส'],
['อายุการใช้งาน', 'ประมาณ 30-50 ปีในอุณหภูมิและแรงดันมาตรฐาน'],
['ความยาวต่อท่อน', '4 เมตรเป็นต้นไป (6 เมตร สำหรับงานราชการ)'],
],
},
{
tableName: 'ประเภทท่อ PVC กับการใช้งาน',
headers: ['ประเภทท่อ', 'รายละเอียด'],
rows: [
['ท่อ PVC ปลายเรียบ', 'เป็นท่อพีวีซีทั่วไป สามารถต่อกับท่อเส้นอื่นผ่านด้วยข้อต่อพีวีซี ทนความดันได้ดี'],
['ท่อ PVC ปลายบาน', 'เป็นท่อที่สามารถเชื่อมต่อกับท่ออื่นได้โดยไม่ต้องผ่านข้อต่อ แต่ยังต้องใช้น้ำยาประสานเพื่อกันรั่วซึม'],
['ท่อ PVC เซาะร่อง', 'ใช้สำหรับเป็นท่อ PVC รับน้ำจากน้ำฝนบนพิ้นดินลำเลียงน้ำสู่บ่อบาดาล มีขนาดเริ่มต้น 2-8 นิ้ว'],
],
},
{
tableName: 'สีท่อ PVC กับการใช้งาน',
headers: ['สีท่อ', 'การใช้งาน'],
rows: [
['ท่อ PVC สีฟ้า', 'ใช้เป็นท่อประปา น้ำดื่ม'],
['ท่อสีเหลือง', 'ใช้กับงานไฟฟ้า'],
['ท่อสีขาว', 'ใช้กับงานไฟฟ้า และร้อยสายโทรศัพท์'],
['ท่อสีเทา', 'ใช้เป็นท่อระบายน้ำทิ้ง หรืองานชลประทาน'],
],
},
{
tableName: 'ขนาดท่อ PVC กับการใช้งาน',
headers: ['ขนาดท่อ', 'การใช้งาน'],
rows: [
['ท่อพีวีซีขนาด ½ นิ้ว (สี่หุน)', 'ท่อขนาดเล็กที่สุด เหมาะสำหรับการใช้งานในบ้าน ท่อประปาภายในบ้าน'],
['ท่อพีวีซีขนาด ¾ นิ้ว (หกหุน)', 'ใช้ในงานน้ำประปา เหมาะสำหรับงานที่ต้องมีการลำเลียงน้ำมากขึ้น'],
['ท่อพีวีซีขนาด 1 นิ้ว', 'ขนาดที่นิยมใช้ในท่อหลักของงานน้ำประปา ใช้ต่อกับข้อต่อเพื่อลดขนาด'],
['ท่อพีวีซีขนาด 1¼ นิ้ว', 'ขนาดที่ไม่ค่อยมีการใช้งานมากนัก ใช้เมื่อต้องการลำเลียงน้ำให้มากขึ้น'],
['ท่อพีวีซีขนาด 1½ นิ้ว', 'ใช้สำหรับระบบท่อน้ำทิ้ง การลำเอียงน้ำจากอ่างไปยังบ่อบำบัด'],
['ท่อพีวีซีขนาด 2 นิ้ว', 'ใช้สำหรับทำระบบท่อน้ำทิ้ง น้ำระบายได้เยอะกว่า โอกาสอุดตันน้อยกว่า'],
['ท่อพีวีซีขนาด 2½ นิ้วขึ้นไป', 'ใช้สำหรับงานเฉพาะทาง การก่อสร้างอาคาร หรืองานเกษตรที่ต้องการจ่ายน้ำจำนวนมาก'],
],
},
{
tableName: 'วิธีการติดตั้ง ท่อ PVC',
headers: ['ขั้นตอน', 'รายละเอียด'],
rows: [
['1. ตัดท่อ', 'ตัดให้ตั้งฉาก ใช้กรรไกรตัดท่อ หรือใช้เลื่อยหากเป็นท่อขนาดใหญ่ แต่งปลายท่อให้เรียบร้อย ปัดเศษขุยออกให้หมด'],
['2. วัดระยะความลึก', 'วัดระยะความลึกในการสวมท่อเข้ากับข้อต่อ'],
['3. ทำความสะอาด', 'ใช้น้ำยาทำความสะอาดท่อ เช็ดทำความสะอาดภายในข้อต่อและท่อ เพื่อลบคราบฝุ่น น้ำมัน หรือสิ่งสกปรก'],
['4. ทาน้ำยาประสานท่อ', 'ทาน้ำยาประสานท่อด้านในข้อต่อ แล้วจึงค่อยทาภายนอกท่อ'],
['5. สวมปลายท่อเข้ากับข้อต่อ', 'ดันให้สุดถึงตำแหน่งที่ทำเครื่องหมายไว้ ดันทิ้งไว้ประมาณ 15 วินาที'],
['6. รอให้แห้ง', 'ก่อนใช้งานควรทิ้งให้น้ำยาประสานท่อแห้งประมาณ 10 นาที'],
],
},
{
tableName: 'แบรนด์ท่อ PVC ที่มีจำหน่าย',
headers: ['แบรนด์'],
rows: [
['ท่อตราช้าง'],
['ท่อน้ำไทย'],
['ท่อตราเสือ'],
['โรงงานทั่วไป'],
],
},
];
// Syler Pipe Tables
export const sylerTables: ProductTable[] = [
{
tableName: 'ท่อเหล็กบุพีอี ไซเลอร์ - ข้อมูลจำเพาะ',
headers: ['คุณสมบัติ', 'รายละเอียด'],
rows: [
['วัสดุ', 'ท่อเหล็กกล้า Class M ชุบสังกะสี บุ PE ทั้งภายในและภายนอก'],
['มาตรฐาน', 'BS1387/85 CLASS M, FM APPROVED, ISO 9001:2000'],
['แรงดันใช้งาน', '50 bar'],
['อุณหภูมิใช้งาน', 'สูงสุด 90°C'],
['ความยาว', '6 เมตร'],
['สี', 'แดง (ระบบดับเพลิง)'],
['อายุการใช้งาน', 'ยาวนานกว่าท่อ Galvanized 50 ปี'],
],
},
{
tableName: 'ขนาดท่อไซเลอร์',
headers: ['ขนาด (นิ้ว)', 'ขนาด (mm)', 'ความหนา (mm)', 'น้ำหนัก (kg/m)'],
rows: [
['1', '25', '3.2', '2.1'],
['1¼', '32', '3.2', '2.8'],
['1½', '40', '3.2', '3.4'],
['2', '50', '3.6', '4.9'],
['2½', '65', '3.6', '6.1'],
['3', '80', '4.0', '8.3'],
['4', '100', '4.0', '10.9'],
['5', '125', '4.0', '13.7'],
['6', '150', '4.5', '18.3'],
],
},
];
// XYLENT Drainage Pipe Tables
export const xylentTables: ProductTable[] = [
{
tableName: 'ท่อระบายน้ำ 3 ชั้น ไซเลนท์ - ข้อมูลจำเพาะ',
headers: ['คุณสมบัติ', 'ค่า'],
rows: [
['วัสดุ', 'PP (Polypropylene) 3 ชั้น'],
['มาตรฐาน', 'EN 1451, DIN 19560'],
['การลดเสียง', '22 dB'],
['อุณหภูมิใช้งาน', '-20 ถึง 95°C'],
['แรงกดทับ', '6 kN/m²'],
['อายุการใช้งาน', '50 ปี'],
['ระบบติดตั้ง', 'Push Fit (สวมล็อค)'],
],
},
{
tableName: 'ขนาดท่อ XYLENT',
headers: ['ขนาด (mm)', 'การใช้งาน'],
rows: [
['32', 'ท่อระบายน้ำในอาคาร'],
['40', 'ท่อระบายน้ำซักล้าง'],
['50', 'ท่อระบายน้ำในห้องน้ำ'],
['75', 'ท่อระบายน้ำหลัก'],
['90', 'ท่อระบายน้ำฝน'],
['110', 'ท่อระบายน้ำโสโครก'],
],
},
{
tableName: 'อุปกรณ์ติดตั้งท่อ XYLENT',
headers: ['อุปกรณ์', 'รายละเอียด'],
rows: [
['Clips', 'ยึดท่อกับผนัง'],
['Brackets', 'รองรับท่อแนวตั้ง'],
['Expansion Joint', 'รองรับการขยายตัวจากความร้อน'],
['Fire Collar', 'ป้องกันไฟลุกลาม'],
],
},
];
// Realflex Flexible Hose Tables
export const realflexTables: ProductTable[] = [
{
tableName: 'Realflex Flexible Hose - ข้อมูลจำเพาะ',
headers: ['คุณสมบัติ', 'ค่า'],
rows: [
['วัสดุ', 'AISI 304 Stainless Steel'],
['แรงดันใช้งาน', '14 bar / 200 psi'],
['แรงดันทดสอบ', '70 bar / 875 psi'],
['อุณหภูมิใช้งาน', 'สูงสุด 107°C / 225°F'],
['มาตรฐาน', 'NFPA13/13D/13R, EN12845'],
['การทดสอบ', 'UL 2443, FM 1637'],
['ความยาว', '1.2m, 1.5m, 1.8m'],
],
},
{
tableName: 'ขนาด Realflex Hose',
headers: ['ขนาด', 'OD (mm)', 'ID (mm)', 'Bend Radius (mm)'],
rows: [
['½"', '15', '10', '40'],
['¾"', '20', '15', '50'],
['1"', '25', '20', '65'],
],
},
];
// POLOPLAST PP-R/PP-RCT Tables
export const poloplastTables: ProductTable[] = [
{
tableName: 'POLOPLAST PP-R SDR 11 (S 5)',
headers: ['ขนาด (mm)', 'ความหนา (mm)', 'น้ำหนัก (kg/m)', 'PN'],
rows: [
['20', '2.0', '0.11', '10'],
['25', '2.3', '0.16', '10'],
['32', '2.9', '0.26', '10'],
['40', '3.7', '0.42', '10'],
['50', '4.6', '0.65', '10'],
['63', '5.8', '1.03', '10'],
['75', '6.8', '1.44', '10'],
['90', '8.2', '2.09', '10'],
['110', '10.0', '3.13', '10'],
],
},
{
tableName: 'POLOPLAST PP-R SDR 6 (S 2.5)',
headers: ['ขนาด (mm)', 'ความหนา (mm)', 'น้ำหนัก (kg/m)', 'PN'],
rows: [
['20', '3.4', '0.18', '20'],
['25', '4.2', '0.28', '20'],
['32', '5.4', '0.46', '20'],
['40', '6.7', '0.72', '20'],
['50', '8.3', '1.12', '20'],
['63', '10.5', '1.78', '20'],
['75', '12.5', '2.53', '20'],
['90', '15.0', '3.65', '20'],
['110', '18.3', '5.45', '20'],
],
},
{
tableName: 'POLOPLAST PP-RCT FIBER ML 5 (SDR 7.4)',
headers: ['ขนาด (mm)', 'ความหนา (mm)', 'น้ำหนัก (kg/m)', 'PN'],
rows: [
['20', '2.8', '0.15', '16'],
['25', '3.5', '0.23', '16'],
['32', '4.4', '0.37', '16'],
['40', '5.5', '0.58', '16'],
['50', '6.9', '0.92', '16'],
['63', '8.6', '1.45', '16'],
['75', '10.3', '2.07', '16'],
['90', '12.3', '3.00', '16'],
['110', '15.1', '4.48', '16'],
],
},
{
tableName: 'เปรียบเทียบ PP-R vs PP-RCT',
headers: ['คุณสมบัติ', 'PP-R', 'PP-RCT'],
rows: [
['อายุการใช้งาน', '50 ปี', '50 ปี'],
['แรงดันใช้งาน', 'สูงสุด PN20', 'สูงสุด PN25'],
['อุณหภูมิสูงสุด', '95°C', '95°C'],
['การยืดขยายตัว', 'ปกติ', 'ลดลง 5 เท่า'],
['ความต้านทานแรงกระแทก', 'ปกติ', 'สูงกว่า'],
],
},
];
// Export all product tables by product ID
export const allProductTables: Record<string, ProductTable[]> = {
dukelarrsen: dukelarrsenTables,
'ppr-welder': pprWelderTables,
'pvc': pvcTables,
'upvc': pvcTables,
'clevis-hanger': clevisHangerTables,
'split-ring-hanger': splitRingHangerTables,
'beam-clamp': beamClampTables,
'band-hanger': bandHangerTables,
'hanger-clamp-bolt': pipeHangerTables,
'syler': sylerTables,
'xylent': xylentTables,
'realflex': realflexTables,
'poloplast': poloplastTables,
};

View File

@@ -1,5 +1,52 @@
import { SiteConfig, NavItem, ProductCategory, WorkHours } from '@/types';
import { dukelarrsenTables, pprWelderTables, pvcTables, clevisHangerTables, splitRingHangerTables, beamClampTables, bandHangerTables, pipeHangerTables, sylerTables, xylentTables, realflexTables, poloplastTables } from './product-tables';
// Deal Plus Tech - Site Configuration
// Types defined inline to avoid circular imports
export interface SiteConfig {
name: string;
nameTh: string;
url: string;
description: string;
phone: string;
email: string;
lineId: string;
facebookUrl: string;
address: string;
}
export interface NavItem {
label: string;
labelEn: string;
href: string;
children?: Array<{ label: string; labelEn: string; href: string; children?: Array<{ label: string; labelEn: string; href: string }> }>;
}
export interface ProductCategory {
id: string;
name: string;
nameEn: string;
slug: string;
href: string;
image: string;
description: string;
shortDescription?: string;
keywords?: string[];
seoContent?: string;
specifications?: Array<{ label: string; value: string; unit?: string }>;
features?: string[];
applications?: string[];
certifications?: string[];
faq?: Array<{ question: string; answer: string }>;
schemaData?: any;
relatedProductIds?: string[];
productTables?: Array<{ tableName: string; headers: string[]; rows: string[][] }>;
}
export interface WorkHours {
day: string;
hours: string;
isClosed?: boolean;
}
export const siteConfig: SiteConfig = {
name: 'Deal Plus Tech',
@@ -212,7 +259,7 @@ export const productCategories: ProductCategory[] = [
material: 'Metal, Plastic',
},
relatedProductIds: ['ppr-elephant', 'thai-ppr', 'poloplast', 'hdpe-welder'],
productTables: pprWelderTables,
},
{
id: 'poloplast',
@@ -278,7 +325,7 @@ export const productCategories: ProductCategory[] = [
material: 'PP-R / PP-RCT',
category: 'Plumbing Pipe - Premium PPR',
},
productTables: poloplastTables,
relatedProductIds: ['ppr-elephant', 'thai-ppr', 'ppr-welder'],
},
@@ -462,7 +509,7 @@ export const productCategories: ProductCategory[] = [
category: 'Plumbing Pipe - uPVC',
},
relatedProductIds: ['pvc', 'xylent'],
productTables: pvcTables,
},
{
id: 'pvc',
@@ -518,7 +565,7 @@ export const productCategories: ProductCategory[] = [
category: 'Plumbing Pipe - PVC',
},
relatedProductIds: ['upvc', 'xylent'],
productTables: pvcTables,
},
{
id: 'syler',
@@ -572,7 +619,7 @@ export const productCategories: ProductCategory[] = [
material: 'Steel with PE Lining',
category: 'Fire Protection Pipe',
},
productTables: sylerTables,
relatedProductIds: ['realflex', 'groove-coupling'],
},
@@ -631,7 +678,7 @@ export const productCategories: ProductCategory[] = [
material: 'Polypropylene (PP) - Triple Layer',
category: 'Drainage Pipe - Silent',
},
productTables: xylentTables,
relatedProductIds: ['poloplast', 'upvc'],
},
@@ -837,7 +884,7 @@ export const productCategories: ProductCategory[] = [
category: 'Grooved Coupling - Fire Protection',
},
relatedProductIds: ['mech', 'groove-coupling', 'syler'],
productTables: dukelarrsenTables,
},
{
id: 'mech',
@@ -932,7 +979,7 @@ export const productCategories: ProductCategory[] = [
category: 'Pipe Support & Hangers',
},
relatedProductIds: ['clevis-hanger', 'split-ring-hanger', 'u-bolt'],
productTables: pipeHangerTables,
},
{
id: 'clevis-hanger',
@@ -978,7 +1025,7 @@ export const productCategories: ProductCategory[] = [
category: 'Pipe Hanger - Clevis Type',
},
relatedProductIds: ['threaded-rod', 'split-ring-hanger'],
productTables: clevisHangerTables,
},
{
id: 'split-ring-hanger',
@@ -1021,7 +1068,7 @@ export const productCategories: ProductCategory[] = [
category: 'Pipe Hanger - Split Ring',
},
relatedProductIds: ['clevis-hanger', 'threaded-rod'],
productTables: splitRingHangerTables,
},
{
id: 'beam-clamp',
@@ -1066,7 +1113,7 @@ export const productCategories: ProductCategory[] = [
category: 'Beam Clamp',
},
relatedProductIds: ['threaded-rod', 'clevis-hanger'],
productTables: beamClampTables,
},
{
id: 'band-hanger',
@@ -1109,7 +1156,7 @@ export const productCategories: ProductCategory[] = [
category: 'Pipe Hanger - Band Type',
},
relatedProductIds: ['split-ring-hanger', 'clevis-hanger'],
productTables: bandHangerTables,
},
{
id: 'level-clamp',
@@ -1559,7 +1606,7 @@ export const productCategories: ProductCategory[] = [
material: 'Stainless Steel 304',
category: 'Fire Protection - Flexible Hose',
},
productTables: realflexTables,
relatedProductIds: ['syler', 'extinguishers'],
},

View File

@@ -0,0 +1,136 @@
---
export interface Props {
title: string;
description?: string;
image?: string;
}
const { title, description, image } = Astro.props;
---
<!doctype html>
<html lang="th">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content={Astro.generator} />
<meta name="description" content={description || 'บริษัท ดีล พลัส เทค จำกัด - ผู้เชี่ยวชาญด้านระบบน้ำ ท่อ PPR ตราช้าง ท่อพีพีอาร์ ท่อ HDPE'} />
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="alternate icon" href="/favicon.ico" sizes="any" />
<link rel="apple-touch-icon" href="/favicon.svg" />
<!-- Google Fonts: Kanit for Thai -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Kanit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<!-- SEO -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description || 'Deal Plus Tech - ผู้เชี่ยวชาญด้านระบบน้ำ'} />
<meta property="og:image" content={image || '/og-image.jpg'} />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<title>{title} | ดีล พลัส เทค</title>
</head>
<body class="flex flex-col min-h-screen">
<slot />
<!-- Cookie Consent Banner -->
<script>
// Check for consent preferences
const consent = JSON.parse(localStorage.getItem('consent-preferences') || 'null');
if (!consent) {
// Dynamically create and show cookie banner
const banner = document.createElement('div');
banner.id = 'cookie-banner';
banner.className = 'fixed bottom-0 left-0 right-0 bg-secondary-900 text-white p-6 z-50 shadow-lg';
banner.innerHTML = `
<div class="container mx-auto max-w-4xl">
<p class="text-lg mb-4">เราใช้คุกกี้เพื่อปรับปรุงประสบการณ์การใช้งานเว็บไซต์ โดยคลิกยอมรับเพื่อใช้งานคุกกี้ทุกประเภท หรือคลิกปรับแต่งเพื่อเลือกคุกกี้ที่ต้องการ</p>
<div class="flex flex-wrap gap-3">
<button id="accept-all" class="px-6 py-2 bg-primary-600 text-white font-semibold rounded-md hover:bg-primary-700">ยอมรับ</button>
<button id="reject-all" class="px-6 py-2 bg-secondary-700 text-white font-semibold rounded-md hover:bg-secondary-600">ปฏิเสธ</button>
<button id="customize" class="px-6 py-2 border border-white text-white font-semibold rounded-md hover:bg-white hover:text-secondary-900">ปรับแต่ง</button>
</div>
</div>
`;
document.body.appendChild(banner);
// Handle button clicks
document.getElementById('accept-all')?.addEventListener('click', () => {
localStorage.setItem('consent-preferences', JSON.stringify({
essential: true,
analytics: true,
marketing: true,
timestamp: new Date().toISOString()
}));
banner.remove();
loadAnalytics();
});
document.getElementById('reject-all')?.addEventListener('click', () => {
localStorage.setItem('consent-preferences', JSON.stringify({
essential: true,
analytics: false,
marketing: false,
timestamp: new Date().toISOString()
}));
banner.remove();
});
document.getElementById('customize')?.addEventListener('click', () => {
// For now, treat as reject - can be enhanced later
localStorage.setItem('consent-preferences', JSON.stringify({
essential: true,
analytics: false,
marketing: false,
timestamp: new Date().toISOString()
}));
banner.remove();
});
} else if (consent.analytics) {
// Load analytics if already consented
loadAnalytics();
}
// Load Umami Analytics if consented
function loadAnalytics() {
// Umami configuration - set in .env
const umamiEnabled = false; // Set to true when Umami is configured
const umamiWebsiteId = ''; // Add your Umami Website ID
const umamiDomain = ''; // e.g., analytics.moreminimore.com
if (umamiEnabled && umamiWebsiteId && umamiDomain) {
const script = document.createElement('script');
script.defer = true;
script.src = `https://${umamiDomain}/script.js`;
script.setAttribute('data-website-id', umamiWebsiteId);
document.head.appendChild(script);
}
}
</script>
</body>
</html>
<style is:global>
html {
font-family: 'Kanit', system-ui, sans-serif;
font-size: 18px;
}
@media (min-width: 1280px) {
html { font-size: 20px; }
}
@media (min-width: 1536px) {
html { font-size: 22px; }
}
@media (min-width: 1920px) {
html { font-size: 24px; }
}
</style>

30
src/lib/umami.ts Normal file
View File

@@ -0,0 +1,30 @@
/**
* Umami Analytics Integration
*
* To enable Umami Analytics:
* 1. Get your Umami Website ID from your Umami dashboard
* 2. Add to .env:
* UMAMI_WEBSITE_ID=your-website-id-here
* UMAMI_DOMAIN=analytics.yourdomain.com
* 3. Set consent.analytics = true in cookie consent
*
* The script will load automatically after user consent.
*/
export const UMAMI_CONFIG = {
enabled: false, // Set to true after configuring .env
websiteId: '', // Add your Umami Website ID
domain: '', // Add your Umami domain (e.g., analytics.moreminimore.com)
};
export function getUmamiScript() {
if (!UMAMI_CONFIG.enabled || !UMAMI_CONFIG.websiteId || !UMAMI_CONFIG.domain) {
return null;
}
return {
src: `https://${UMAMI_CONFIG.domain}/script.js`,
'data-website-id': UMAMI_CONFIG.websiteId,
defer: true,
};
}

View File

@@ -1,27 +1,42 @@
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
// Utility functions migrated from Next.js
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
/**
* Combines class names conditionally (like clsx + tailwind-merge)
*/
export function cn(...classes: Array<string | false | null | undefined>): string {
return classes.filter(Boolean).join(' ');
}
export function formatDate(date: string): string {
return new Date(date).toLocaleDateString('th-TH', {
/**
* Format price in Thai Baht
*/
export function formatPrice(price: number): string {
return new Intl.NumberFormat('th-TH', {
style: 'currency',
currency: 'THB',
}).format(price);
}
/**
* Format date to Thai locale
*/
export function formatDateThai(date: Date | string): string {
return new Intl.DateTimeFormat('th-TH', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
}).format(new Date(date));
}
export function truncate(str: string, length: number): string {
if (str.length <= length) return str;
return str.slice(0, length) + '...';
}
export function slugify(str: string): string {
return str
/**
* Generate slug from Thai text
*/
export function generateSlug(text: string): string {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
.replace(/\s+/g, '-')
.replace(/[^\w-]+/g, '')
.replace(/--+/g, '-')
.replace(/^-+/, '')
.replace(/-+$/, '');
}

View File

@@ -0,0 +1,116 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import FloatingContact from '../../components/FloatingContact.astro';
import { siteConfig } from '../../data/site-config';
---
<BaseLayout title="เกี่ยวกับเรา" description="เรียนรู้เพิ่มเติมเกี่ยวกับดีลพลัสเทค ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ">
<main class="pt-32 pb-16">
<div class="container mx-auto px-4">
<!-- Hero -->
<div class="relative h-[400px] -mt-32 mb-12 rounded-b-3xl overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-800 to-secondary-900" />
<div class="absolute inset-0 flex items-center justify-center">
<div class="text-center">
<h1 class="text-4xl md:text-5xl font-bold text-white mb-4">
เกี่ยวกับ<span class="text-primary-400">{siteConfig.name}</span>
</h1>
<p class="text-xl text-secondary-200">
ผู้เชี่ยวชาญด้านวัสดุท่อและอุปกรณ์ระบบท่อ
</p>
</div>
</div>
</div>
<!-- Company Story -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 mb-16">
<div>
<h2 class="text-3xl font-bold text-secondary-900 mb-6">เรื่องราวของเรา</h2>
<div class="space-y-4 text-secondary-600">
<p>
{siteConfig.nameTh} ก่อตั้งขึ้นด้วยความมุ่งมั่นที่จะเป็นผู้นำด้านการจัดหาวัสดุท่อ
และอุปกรณ์ระบบท่อคุณภาพสูงให้กับลูกค้าในประเทศไทย
</p>
<p>
ด้วยประสบการณ์มากกว่า 10 ปีในอุตสาหกรรม เราได้สั่งสมความเชี่ยวชาญ
และสร้างเครือข่ายความร่วมมือกับผู้ผลิตชั้นนำทั้งในและต่างประเทศ
</p>
<p>
เรามุ่งมั่นให้บริการสินค้าที่ผ่านมาตรฐานคุณภาพ พร้อมคำแนะนำจากทีมงานมืออาชีพ
เพื่อให้ลูกค้าได้รับสินค้าที่เหมาะสมกับความต้องการ
</p>
</div>
</div>
<div class="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<img
src="/images/2021/03/hdpe-pipe_000C.jpg"
alt="เกี่ยวกับดีลพลัสเทค"
class="object-cover w-full h-full"
loading="lazy"
/>
</div>
</div>
<!-- Vision & Mission -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16">
<div class="bg-secondary-800 p-8 rounded-xl">
<h3 class="text-2xl font-bold text-primary-400 mb-4">วิสัยทัศน์</h3>
<p class="text-secondary-200">
เป็นผู้นำตลาดวัสดุท่อและอุปกรณ์ระบบท่อในประเทศไทย
ที่ลูกค้าไว้วางใจในคุณภาพและการบริการ
</p>
</div>
<div class="bg-secondary-800 p-8 rounded-xl">
<h3 class="text-2xl font-bold text-primary-400 mb-4">พันธกิจ</h3>
<p class="text-secondary-200">
จัดหาสินค้าคุณภาพสูง ให้บริการที่เป็นเลิศ และสร้างความพึงพอใจสูงสุดให้ลูกค้า
</p>
</div>
</div>
<!-- Core Values -->
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-secondary-900 mb-8">ค่านิยมหลัก</h2>
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
<div class="p-6 bg-primary-50 rounded-xl">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 class="font-bold text-secondary-900 mb-2">คุณภาพ</h4>
<p class="text-secondary-600 text-sm">สินค้าผ่านมาตรฐาน</p>
</div>
<div class="p-6 bg-primary-50 rounded-xl">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 class="font-bold text-secondary-900 mb-2">รวดเร็ว</h4>
<p class="text-secondary-600 text-sm">จัดส่งรวดเร็วทันใจ</p>
</div>
<div class="p-6 bg-primary-50 rounded-xl">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
</div>
<h4 class="font-bold text-secondary-900 mb-2">บริการ</h4>
<p class="text-secondary-600 text-sm">ทีมงานมืออาชีพ</p>
</div>
<div class="p-6 bg-primary-50 rounded-xl">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<h4 class="font-bold text-secondary-900 mb-2">ไว้ใจ</h4>
<p class="text-secondary-600 text-sm">ซื่อสัตย์ต่อลูกค้า</p>
</div>
</div>
</div>
</div>
</main>
<FloatingContact />
</BaseLayout>

View File

@@ -0,0 +1,75 @@
---
import { getCollection, render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.id },
props: { post },
}));
}
interface Props {
post: CollectionEntry<'blog'>;
}
const { post } = Astro.props;
const { Content } = await render(post);
const { title, date, author, category, categories, image, featuredImage } = post.data;
// Support both 'category' and 'categories'
const postCategory = category || (Array.isArray(categories) ? categories[0] : 'ทั่วไป');
const postImage = image || featuredImage || '/images/2021/03/ppr-pipe_000C.jpg';
---
<BaseLayout title={title} description={post.data.excerpt}>
<main class="pt-32 pb-16">
<article class="container mx-auto px-4 max-w-4xl">
<!-- Header -->
<header class="mb-8">
<div class="flex items-center gap-4 mb-4">
<span class="industrial-badge">{postCategory}</span>
<time class="text-secondary-500">
{new Date(date).toLocaleDateString('th-TH', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</time>
<span class="text-secondary-500">•</span>
<span class="text-secondary-500">{author}</span>
</div>
<h1 class="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
{title}
</h1>
</header>
<!-- Featured Image -->
<div class="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden mb-8">
<img
src={postImage}
alt={title}
class="object-cover w-full h-full"
loading="lazy"
/>
</div>
<!-- Content -->
<div class="prose prose-lg max-w-none prose-headings:font-bold prose-a:text-primary-600 hover:prose-a:text-primary-700 prose-img:rounded-xl">
<Content />
</div>
<!-- Back to Blog -->
<div class="mt-12 pt-8 border-t border-secondary-200">
<a href="/blog/" class="inline-flex items-center text-primary-600 font-medium hover:text-primary-700 transition-colors">
<svg class="w-5 h-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
กลับสู่หน้าบทความ
</a>
</div>
</article>
</main>
</BaseLayout>

View File

@@ -0,0 +1,37 @@
---
import { getCollection } from 'astro:content';
import BlogCard from '../../components/BlogCard.astro';
import BaseLayout from '../../layouts/BaseLayout.astro';
const posts = await getCollection('blog');
export const metadata = {
title: 'บทความความรู้',
description: 'บทความความรู้เกี่ยวกับวัสดุท่อ อุปกรณ์ระบบท่อ และเทคนิคการติดตั้ง',
};
export const prerender = true;
---
<BaseLayout title={metadata.title} description={metadata.description}>
<main class="pt-32 pb-16">
<div class="container mx-auto px-4">
<!-- Hero -->
<div class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold text-secondary-900 mb-4">
บทความ<span class="text-primary-600">ความรู้</span>
</h1>
<p class="text-xl text-secondary-600 max-w-2xl mx-auto">
บทความความรู้เกี่ยวกับวัสดุท่อ อุปกรณ์ระบบท่อ และเทคนิคการติดตั้ง
</p>
</div>
<!-- Blog Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{posts.map((post) => (
<BlogCard post={post} />
))}
</div>
</div>
</main>
</BaseLayout>

View File

@@ -0,0 +1,156 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="นโยบายคุกกี้"
description="นโยบายการใช้งานคุกกี้ของเว็บไซต์บริษัท ดีล พลัส เทค จำกัด"
>
<main class="min-h-screen bg-secondary-50">
<div class="container mx-auto px-4 py-12">
<div class="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-8 md:p-12">
<h1 class="text-4xl font-bold text-secondary-900 mb-4">นโยบายคุกกี้</h1>
<p class="text-secondary-600 mb-8">Cookie Policy - ปรับปรุงล่าสุด: 9 มีนาคม 2026</p>
<div class="prose prose-lg max-w-none text-secondary-700">
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">1. คุกกี้คืออะไร?</h2>
<p class="mb-4">
คุกกี้ (Cookie) คือไฟล์ข้อความขนาดเล็กที่เว็บไซต์บันทึกลงบนอุปกรณ์ของท่าน
(คอมพิวเตอร์, แท็บเล็ต, หรือมือถือ) เมื่อท่านเยี่ยมชมเว็บไซต์
คุกกี้ช่วยให้เว็บไซต์จดจำการกระทำและความชอบของท่าน ทำให้ประสบการณ์การใช้งานดีขึ้น
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">2. ประเภทคุกกี้ที่เราใช้</h2>
<p class="mb-4">เราใช้คุกกี้ 3 ประเภท:</p>
<div class="space-y-4">
<div class="bg-secondary-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold mb-2">🔒 คุกกี้ที่จำเป็น (Essential Cookies)</h3>
<p class="text-sm">
คุกกี้เหล่านี้จำเป็นสำหรับการทำงานของเว็บไซต์ ไม่สามารถปิดใช้งานได้
ใช้สำหรับ: การจัดการเซสชัน, ความปลอดภัย, การทำงานพื้นฐานของเว็บไซต์
</p>
<p class="text-sm mt-2"><strong>ความยินยอม:</strong> ไม่จำเป็น (เปิดเสมอ)</p>
</div>
<div class="bg-secondary-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold mb-2">📊 คุกกี้วิเคราะห์ (Analytics Cookies)</h3>
<p class="text-sm">
คุกกี้เหล่านี้帮助我们เก็บข้อมูลการใช้งานเว็บไซต์แบบไม่ระบุตัวตน
ใช้สำหรับ: การวิเคราะห์ผู้เยี่ยมชม, หน้าเว็บที่นิยม, อัตราการตีกลับ
</p>
<p class="text-sm mt-2"><strong>ความยินยอม:</strong> ต้องเปิดใช้งาน (Opt-in)</p>
</div>
<div class="bg-secondary-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold mb-2">📢 คุกกี้การตลาด (Marketing Cookies)</h3>
<p class="text-sm">
คุกกี้เหล่านี้ใช้เพื่อติดตามผู้ใช้งานบนเว็บไซต์ต่าง ๆ
ใช้สำหรับ: การโฆษณาที่กำหนดเป้าหมาย, การวัดประสิทธิภาพโฆษณา
</p>
<p class="text-sm mt-2"><strong>ความยินยอม:</strong> ต้องเปิดใช้งาน (Opt-in)</p>
</div>
</div>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">3. คุกกี้ที่เราใช้</h2>
<div class="overflow-x-auto">
<table class="min-w-full border">
<thead class="bg-secondary-100">
<tr>
<th class="px-4 py-2 border text-left">ชื่อคุกกี้</th>
<th class="px-4 py-2 border text-left">ประเภท</th>
<th class="px-4 py-2 border text-left">ระยะเวลา</th>
<th class="px-4 py-2 border text-left">วัตถุประสงค์</th>
</tr>
</thead>
<tbody>
<tr>
<td class="px-4 py-2 border">session_id</td>
<td class="px-4 py-2 border">จำเป็น</td>
<td class="px-4 py-2 border">จนกว่าจะปิดเบราว์เซอร์</td>
<td class="px-4 py-2 border">จัดการเซสชัน</td>
</tr>
<tr>
<td class="px-4 py-2 border">consent-preferences</td>
<td class="px-4 py-2 border">จำเป็น</td>
<td class="px-4 py-2 border">1 ปี</td>
<td class="px-4 py-2 border">บันทึกการตั้งค่าคุกกี้</td>
</tr>
<tr>
<td class="px-4 py-2 border">umami analytics</td>
<td class="px-4 py-2 border">วิเคราะห์</td>
<td class="px-4 py-2 border">ไม่ใช้คุกกี้</td>
<td class="px-4 py-2 border">วิเคราะห์การใช้งาน (Privacy-first)</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">4. การจัดการคุกกี้</h2>
<p class="mb-4">ท่านสามารถจัดการการตั้งค่าคุกกี้ได้โดย:</p>
<ul class="list-disc pl-6 space-y-2">
<li><strong>แบนเนอร์คุกกี้:</strong> คลิกที่ปุ่ม "ปรับแต่ง" ในแบนเนอร์คุกกี้เพื่อเลือกคุกกี้ที่ต้องการ</li>
<li><strong>การตั้งค่าเบราว์เซอร์:</strong> เบราว์เซอร์ส่วนใหญ่ยอมให้ท่านบล็อกหรือลบคุกกี้ได้</li>
<li><strong>ลิงก์ในฟุตเตอร์:</strong> คลิก "การตั้งค่าคุกกี้" ที่ด้านล่างของหน้าเว็บ</li>
</ul>
<p class="mt-4">
<a href="#" id="openPreferences" class="text-primary-600 hover:underline font-semibold">
→ เปิดการตั้งค่าคุกกี้ตอนนี้
</a>
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">5. การเพิกถอนความยินยอม</h2>
<p class="mb-4">
ท่านสามารถเพิกถอนความยินยอมสำหรับคุกกี้วิเคราะห์และคุกกี้การตลาดเมื่อใดก็ได้
โดยไปที่การตั้งค่าคุกกี้และปิดการใช้งานคุกกี้เหล่านั้น
การเพิกถอนความยินยอมจะไม่มีผลต่อความถูกต้องของการประมวลผลก่อนการเพิกถอน
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">6. การอัปเดตนโยบาย</h2>
<p class="mb-4">
เราอาจอัปเดตนโยบายคุกกี้นี้เป็นครั้งคราว การเปลี่ยนแปลงใด ๆ จะถูกเผยแพร่บนหน้านี้
กรุณาตรวจสอบหน้าทนี้เป็นระยะเพื่อดูการเปลี่ยนแปลง
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">7. การติดต่อ</h2>
<p class="mb-4">หากมีคำถามเกี่ยวกับนโยบายคุกกี้นี้ กรุณาติดต่อ:</p>
<div class="bg-secondary-50 p-4 rounded-lg">
<p><strong>บริษัท ดีล พลัส เทค จำกัด</strong></p>
<p>อีเมล: info@dealplustech.co.th</p>
<p>โทรศัพท์: 090-555-1415</p>
</div>
</section>
<section class="mt-12 pt-8 border-t border-secondary-200">
<p class="text-sm text-secondary-600">
อ่านเพิ่มเติม: <a href="/privacy-policy/" class="text-primary-600 hover:underline">นโยบายความเป็นส่วนตัว</a> |
<a href="/terms-and-conditions/" class="text-primary-600 hover:underline">ข้อกำหนดและเงื่อนไข</a>
</p>
</section>
</div>
</div>
</div>
</main>
</BaseLayout>
<script>
// Open cookie preferences when clicked
document.getElementById('openPreferences')?.addEventListener('click', (e) => {
e.preventDefault();
// Dispatch custom event to open cookie preferences modal
window.dispatchEvent(new CustomEvent('open-cookie-preferences'));
});
</script>

186
src/pages/index.astro Normal file
View File

@@ -0,0 +1,186 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import FloatingContact from '../components/FloatingContact.astro';
import { productCategories } from '../data/site-config';
// Featured products - key products for homepage
const featuredProducts = productCategories.filter(p =>
['ppr-elephant', 'hdpe', 'poloplast', 'syler', 'xylent'].includes(p.id)
).slice(0, 6);
---
<BaseLayout title="หน้าแรก" description="บริษัท ดีล พลัส เทค จำกัด - ผู้เชี่ยวชาญด้านระบบท่อและ HVAC">
<main>
<!-- Hero Section -->
<section class="relative h-[70vh] min-h-[500px] bg-secondary-900">
<div class="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-900/90 to-secondary-900/60 z-10" />
<img
src="/images/2021/03/ppr-pipe_000C.jpg"
alt="ท่อพีพีอาร์คุณภาพสูง"
class="absolute inset-0 w-full h-full object-cover opacity-50"
loading="eager"
/>
<div class="relative z-20 container mx-auto px-4 h-full flex items-center">
<div class="max-w-2xl">
<span class="inline-block px-4 py-2 bg-primary-600 text-white font-semibold mb-4 rounded">
ผู้เชี่ยวชาญด้านระบบท่อและ HVAC
</span>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-6 leading-tight">
วัสดุท่อ อุปกรณ์ HVAC
<span class="text-primary-400 block">และฉนวนหุ้มท่อ</span>
</h1>
<p class="text-lg md:text-xl text-secondary-200 mb-8">
จำหน่ายและติดตั้งท่อ PPR, ท่อ HDPE, กริลแอร์, เทอร์โมเบรค และอุปกรณ์ระบบท่อครบวงจร พร้อมบริการให้คำปรึกษาจากทีมมืออาชีพ
</p>
<div class="flex flex-wrap gap-4">
<a href="/products/" class="btn-primary">
ดูสินค้าทั้งหมด
</a>
<a href="/contact-us/" class="btn-outline border-white text-white hover:bg-white hover:text-secondary-900">
ขอใบเสนอราคา
</a>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section class="py-16 bg-secondary-800">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="text-center p-6">
<div class="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
</div>
<h3 class="text-xl font-bold text-white mb-2">สินค้าคุณภาพ</h3>
<p class="text-secondary-300">
สินค้าทุกชิ้นผ่านมาตรฐานคุณภาพ พร้อมรับประกัน
</p>
</div>
<div class="text-center p-6">
<div class="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<h3 class="text-xl font-bold text-white mb-2">จัดส่งรวดเร็ว</h3>
<p class="text-secondary-300">
จัดส่งสินค้าทั่วประเทศ รวดเร็วและปลอดภัย
</p>
</div>
<div class="text-center p-6">
<div class="w-16 h-16 bg-primary-600 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
<h3 class="text-xl font-bold text-white mb-2">บริการหลังการขาย</h3>
<p class="text-secondary-300">
ทีมงานพร้อมให้คำปรึกษาและดูแลอย่างต่อเนื่อง
</p>
</div>
</div>
</div>
</section>
<!-- Featured Products -->
<section class="py-16 bg-secondary-50">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl md:text-4xl font-bold text-secondary-900 mb-4">
สินค้า<span class="text-primary-600">เด่น</span>
</h2>
<p class="text-secondary-600 text-lg">ผลิตภัณฑ์คุณภาพสูงที่ได้รับความนิยม</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{featuredProducts.map((product) => (
<a href={product.href} class="card group">
<div class="relative aspect-video bg-secondary-100 overflow-hidden">
<img
src={product.image}
alt={product.name}
class="object-cover w-full h-48 group-hover:scale-105 transition-transform duration-300"
loading="lazy"
/>
</div>
<div class="p-6">
<h3 class="text-lg font-bold text-secondary-900 group-hover:text-primary-600 transition-colors">
{product.name}
</h3>
<p class="mt-2 text-sm text-secondary-600 line-clamp-2">
{product.shortDescription || product.description}
</p>
<div class="mt-4 flex items-center text-primary-600 font-medium">
<span>ดูรายละเอียด</span>
<svg class="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</a>
))}
</div>
<div class="text-center mt-12">
<a href="/products/" class="btn-primary">
ดูสินค้าทั้งหมด
</a>
</div>
</div>
</section>
<!-- About Preview -->
<section class="py-16 bg-white">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h2 class="text-3xl md:text-4xl font-bold text-secondary-900 mb-6">
เกี่ยวกับ<span class="text-primary-600">เรา</span>
</h2>
<p class="text-lg text-secondary-600 mb-6">
บริษัท ดีล พลัส เทค จำกัด เราเป็นผู้เชียวชาญด้านระบบน้ำ ให้คำแนะนำและจำหน่ายท่อ PPR ตราช้าง ท่อพีพีอาร์ ท่อ PPR ท่อ HDPE Thai PPR คุณภาพสูง ราคาถูก
</p>
<p class="text-secondary-700 mb-8">
ด้วยประสบการณ์ยาวนาน เราพร้อมให้บริการสินค้าคุณภาพและคำแนะนำจากผู้เชี่ยวชาญ เพื่อให้งานระบบของคุณมีประสิทธิภาพสูงสุด
</p>
<a href="/about-us/" class="btn-secondary">
อ่านเพิ่มเติม
</a>
</div>
<div class="relative aspect-video bg-secondary-100 rounded-xl overflow-hidden">
<img
src="/images/2021/03/ppr-pipe_000C.jpg"
alt="เกี่ยวกับดีลพลัสเทค"
class="object-cover w-full h-full"
loading="lazy"
/>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 bg-primary-600">
<div class="container mx-auto px-4 text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">
สนใจสินค้าหรือต้องการคำปรึกษา?
</h2>
<p class="text-xl text-primary-100 mb-8 max-w-2xl mx-auto">
ทีมงานของเราพร้อมให้คำแนะนำและช่วยคุณเลือกสินค้าที่เหมาะสมที่สุด
</p>
<div class="flex flex-wrap justify-center gap-4">
<a href="tel:090-555-1415" class="btn-secondary bg-white text-primary-600 hover:bg-primary-50">
โทร: 090-555-1415
</a>
<a href="https://line.me/ti/p/@dealplustech" target="_blank" rel="noopener" class="btn-outline border-white text-white hover:bg-white hover:text-primary-600">
เพิ่มเพื่อน LINE
</a>
</div>
</div>
</section>
</main>
<FloatingContact />
</BaseLayout>

View File

@@ -0,0 +1,171 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="นโยบายความเป็นส่วนตัว"
description="นโยบายความเป็นส่วนตัวตามกฎหมายคุ้มครองข้อมูลส่วนบุคคล (PDPA) ของบริษัท ดีล พลัส เทค จำกัด"
>
<main class="min-h-screen bg-secondary-50">
<div class="container mx-auto px-4 py-12">
<div class="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-8 md:p-12">
<h1 class="text-4xl font-bold text-secondary-900 mb-4">นโยบายความเป็นส่วนตัว</h1>
<p class="text-secondary-600 mb-8">Privacy Policy - ปรับปรุงล่าสุด: 9 มีนาคม 2026</p>
<nav class="mb-8 p-4 bg-secondary-50 rounded-lg">
<h2 class="text-lg font-semibold mb-3">สารบัญ</h2>
<ul class="space-y-1 text-primary-600">
<li><a href="#section1" class="hover:underline">1. ข้อมูลผู้ควบคุมข้อมูลส่วนบุคคล</a></li>
<li><a href="#section2" class="hover:underline">2. ประเภทข้อมูลที่เก็บรวบรวม</a></li>
<li><a href="#section3" class="hover:underline">3. วัตถุประสงค์การเก็บรวบรวม</a></li>
<li><a href="#section4" class="hover:underline">4. ฐานทางกฎหมายสำหรับการประมวลผล</a></li>
<li><a href="#section5" class="hover:underline">5. ระยะเวลาเก็บรักษาข้อมูล</a></li>
<li><a href="#section6" class="hover:underline">6. การเปิดเผยข้อมูล</a></li>
<li><a href="#section9" class="hover:underline">7. คุกกี้และเทคโนโลยีการติดตาม</a></li>
<li><a href="#section10" class="hover:underline">8. สิทธิของเจ้าของข้อมูล</a></li>
<li><a href="#section11" class="hover:underline">9. มาตรการรักษาความปลอดภัย</a></li>
<li><a href="#section13" class="hover:underline">10. สิทธิร้องเรียน</a></li>
</ul>
</nav>
<div class="prose prose-lg max-w-none">
<section id="section1" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">1. ข้อมูลผู้ควบคุมข้อมูลส่วนบุคคล</h2>
<p class="text-secondary-700 mb-4">
<strong>บริษัท ดีล พลัส เทค จำกัด</strong> เป็นผู้ควบคุมข้อมูลส่วนบุคคล (Data Controller)
ซึ่งมีหน้าที่ในการตัดสินใจเกี่ยวกับการเก็บรวบรวม ใช้ หรือเปิดเผยข้อมูลส่วนบุคคล
</p>
<div class="bg-secondary-50 p-4 rounded-lg">
<p class="text-secondary-700"><strong>ที่อยู่:</strong> 9/70 ซอยนครลุง 17 แขวงบางไผ่ เขตบางแค กทม. 10160</p>
<p class="text-secondary-700"><strong>เบอร์โทรศัพท์:</strong> 090-555-1415</p>
<p class="text-secondary-700"><strong>อีเมล:</strong> info@dealplustech.co.th</p>
</div>
</section>
<section id="section2" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">2. ประเภทข้อมูลที่เก็บรวบรวม</h2>
<p class="text-secondary-700 mb-4">เราเก็บรวบรวมข้อมูลส่วนบุคคลดังนี้:</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li><strong>ข้อมูลส่วนบุคคลทั่วไป:</strong> ชื่อ, นามสกุล, ที่อยู่อีเมล, เบอร์โทรศัพท์</li>
<li><strong>ข้อมูลการใช้งาน:</strong> IP Address, Browser Type, Device Information, Cookie Data</li>
<li><strong>ข้อมูลการติดต่อ:</strong> ข้อความหรือคำถามที่ท่านส่งถึงเรา</li>
</ul>
</section>
<section id="section3" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">3. วัตถุประสงค์การเก็บรวบรวม</h2>
<p class="text-secondary-700 mb-4">เราเก็บรวบรวมข้อมูลเพื่อวัตถุประสงค์ดังนี้:</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li>เพื่อให้บริการและตอบคำถามหรือคำขอของท่าน</li>
<li>เพื่อปรับปรุงประสบการณ์การใช้งานเว็บไซต์</li>
<li>เพื่อส่งข้อมูลข่าวสารและการตลาด (เมื่อได้รับความยินยอม)</li>
<li>เพื่อวิเคราะห์และปรับปรุงบริการของเรา</li>
<li>เพื่อปฏิบัติตามกฎหมายและข้อบังคับที่เกี่ยวข้อง</li>
</ul>
</section>
<section id="section4" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">4. ฐานทางกฎหมายสำหรับการประมวลผล</h2>
<p class="text-secondary-700 mb-4">เราประมวลผลข้อมูลส่วนบุคคลภายใต้ฐานทางกฎหมายดังนี้:</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li><strong>ความยินยอม (Consent):</strong> สำหรับการส่งข้อมูลการตลาดและการใช้คุกกี้บางประเภท</li>
<li><strong>การปฏิบัติตามสัญญา (Contract):</strong> เพื่อให้บริการที่ท่านร้องขอ</li>
<li><strong>ผลประโยชน์โดยชอบด้วยกฎหมาย (Legitimate Interest):</strong> เพื่อปรับปรุงบริการและวิเคราะห์การใช้งาน</li>
<li><strong>การปฏิบัติตามกฎหมาย (Legal Obligation):</strong> เมื่อจำเป็นต้องปฏิบัติตามกฎหมาย</li>
</ul>
</section>
<section id="section5" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">5. ระยะเวลาเก็บรักษาข้อมูล</h2>
<p class="text-secondary-700 mb-4">
เราเก็บรักษาข้อมูลส่วนบุคคลเป็นเวลา <strong>10 ปี</strong> ตามข้อกำหนดของกฎหมาย PDPA
หรือตราบเท่าที่จำเป็นสำหรับวัตถุประสงค์ที่ระบุไว้ข้างต้น
หลังจากสิ้นสุดระยะเวลาเก็บรักษา เราจะทำลายหรือทำให้ข้อมูลไม่สามารถระบุตัวตนได้
</p>
</section>
<section id="section6" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">6. การเปิดเผยข้อมูล</h2>
<p class="text-secondary-700 mb-4">
เราจะไม่เปิดเผยข้อมูลส่วนบุคคลของท่านให้กับบุคคลภายนอก เว้นแต่:
</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li>ท่านให้ความยินยอมอย่างชัดเจน</li>
<li>จำเป็นต้องปฏิบัติตามกฎหมายหรือคำสั่งศาล</li>
<li>จำเป็นสำหรับการให้บริการที่ท่านร้องขอ (เช่น ผู้ให้บริการจัดส่ง)</li>
<li>เพื่อปกป้องสิทธิและความปลอดภัยของเราและผู้อื่น</li>
</ul>
</section>
<section id="section9" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">7. คุกกี้และเทคโนโลยีการติดตาม</h2>
<p class="text-secondary-700 mb-4">
เราใช้คุกกี้และเทคโนโลยีการติดตามเพื่อปรับปรุงประสบการณ์การใช้งานเว็บไซต์ ท่านสามารถจัดการการตั้งค่าคุกกี้ได้ที่
<a href="/cookie-policy/" class="text-primary-600 hover:underline">นโยบายคุกกี้</a>
</p>
</section>
<section id="section10" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">8. สิทธิของเจ้าของข้อมูล</h2>
<p class="text-secondary-700 mb-4">
ภายใต้กฎหมาย PDPA ท่านมีสิทธิดังต่อไปนี้:
</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li><strong>สิทธิขอเข้าถึง:</strong> ขอรับสำเนาข้อมูลส่วนบุคคลที่ท่านให้ไว้</li>
<li><strong>สิทธิขอแก้ไข:</strong> ขอให้แก้ไขข้อมูลที่ไม่ถูกต้อง</li>
<li><strong>สิทธิขอ ลบ:</strong> ขอให้ ลบข้อมูลส่วนบุคคล (Right to Erasure)</li>
<li><strong>สิทธิขอระงับ:</strong> ขอให้ระงับการประมวลผลข้อมูล</li>
<li><strong>สิทธิขอพกพา:</strong> ขอรับข้อมูลในรูปแบบที่อ่านได้ทั่วไป</li>
<li><strong>สิทธิคัดค้าน:</strong> คัดค้านการประมวลผลข้อมูล</li>
<li><strong>สิทธิเพิกถอนความยินยอม:</strong> เพิกถอนความยินยอมที่ได้ให้ไว้ก่อนหน้า</li>
<li><strong>สิทธิร้องเรียน:</strong> ร้องเรียนต่อคณะกรรมการคุ้มครองข้อมูลส่วนบุคคล</li>
</ul>
<p class="text-secondary-700 mt-4">
หากท่านต้องการใช้สิทธิเหล่านี้ กรุณาติดต่อเราที่ info@dealplustech.co.th
</p>
</section>
<section id="section11" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">9. มาตรการรักษาความปลอดภัย</h2>
<p class="text-secondary-700 mb-4">
เราใช้มาตรการรักษาความปลอดภัยที่เหมาะสมเพื่อปกป้องข้อมูลส่วนบุคคลของท่านจากการเข้าถึง
การใช้ การแก้ไข หรือการเปิดเผยโดยไม่ได้รับอนุญาต มาตรการเหล่านี้รวมถึง:
</p>
<ul class="list-disc pl-6 space-y-2 text-secondary-700">
<li>การเข้ารหัสข้อมูล (Encryption)</li>
<li>การควบคุมการเข้าถึง (Access Control)</li>
<li>การสำรองข้อมูลเป็นประจำ</li>
<li>การฝึกอบรมพนักงานเรื่องการคุ้มครองข้อมูล</li>
</ul>
</section>
<section id="section13" class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">10. สิทธิร้องเรียน</h2>
<p class="text-secondary-700 mb-4">
หากท่านเชื่อว่ามีการละเมิดกฎหมาย PDPA ท่านมีสิทธิร้องเรียนต่อ:
</p>
<div class="bg-secondary-50 p-4 rounded-lg">
<p class="text-secondary-700">
<strong>คณะกรรมการคุ้มครองข้อมูลส่วนบุคคล (PDPC)</strong>
</p>
<p class="text-secondary-700">เว็บไซต์: www.pdpc.or.th</p>
<p class="text-secondary-700">อีเมล: info@pdpc.or.th</p>
</div>
</section>
<section class="mt-12 pt-8 border-t border-secondary-200">
<h2 class="text-xl font-bold text-secondary-900 mb-4">การติดต่อ</h2>
<p class="text-secondary-700">
หากมีคำถามเกี่ยวกับนโยบายความเป็นส่วนตัวนี้ กรุณาติดต่อ:
</p>
<div class="mt-4">
<p class="text-secondary-700"><strong>บริษัท ดีล พลัส เทค จำกัด</strong></p>
<p class="text-secondary-700">อีเมล: info@dealplustech.co.th</p>
<p class="text-secondary-700">โทรศัพท์: 090-555-1415</p>
</div>
</section>
</div>
</div>
</div>
</main>
</BaseLayout>

View File

@@ -0,0 +1,21 @@
---
import { getCollection } from 'astro:content';
import ProductCard from '../../components/ProductCard.astro';
import BaseLayout from '../../layouts/BaseLayout.astro';
const products = await getCollection('products');
---
<BaseLayout title="สินค้าทั้งหมด" description="รายการสินค้าทั้งหมดจาก Deal Plus Tech">
<main class="py-12">
<div class="container mx-auto px-4 max-w-6xl">
<h1 class="section-title mb-8">สินค้าทั้งหมด</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{products.map((product) => (
<ProductCard product={product} />
))}
</div>
</div>
</main>
</BaseLayout>

View File

@@ -0,0 +1,270 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import FloatingContact from '../../components/FloatingContact.astro';
---
<BaseLayout title="บริการของเรา" description="บริการครบวงจร จำหน่ายวัสดุท่อ ให้คำปรึกษา ออกแบบระบบ และติดตั้ง">
<main>
<!-- Hero Section -->
<section class="relative h-[50vh] min-h-[400px] bg-secondary-900">
<div class="absolute inset-0 bg-gradient-to-r from-secondary-900 via-secondary-900/90 to-secondary-900/60 z-10" />
<img
src="/images/2021/03/hdpe-pipe_000C.jpg"
alt="บริการของเรา"
class="absolute inset-0 w-full h-full object-cover opacity-40"
loading="eager"
/>
<div class="relative z-20 container mx-auto px-4 h-full flex items-center">
<div class="max-w-2xl">
<span class="inline-block px-4 py-2 bg-primary-600 text-white font-semibold mb-4 rounded">
บริการครบวงจร
</span>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-6">
บริการ<span class="text-primary-400">ของเรา</span>
</h1>
<p class="text-xl text-secondary-200">
ตั้งแต่การให้คำปรึกษา ออกแบบ จัดส่ง จนถึงติดตั้ง เราพร้อมดูแลโครงการของคุณครบวงจร
</p>
</div>
</div>
</section>
<!-- Services Grid -->
<section class="py-20 bg-white">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Service 1 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
จำหน่ายวัสดุท่อ
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
จำหน่ายท่อพีพีอาร์ ท่อ HDPE ท่อ PVC วาล์ว และอุปกรณ์ต่อท่อครบวงจร สินค้าคุณภาพ ราคาแข่งขันได้
</p>
</div>
<!-- Service 2 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
ให้คำปรึกษา
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
ทีมงานมืออาชีพพร้อมให้คำปรึกษาเกี่ยวกับการเลือกวัสดุท่อที่เหมาะสมกับโครงการของคุณ
</p>
</div>
<!-- Service 3 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
ออกแบบระบบ
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
บริการออกแบบระบบท่อน้ำ ระบบดับเพลิง และระบบปรับอากาศ โดยวิศวกรผู้เชี่ยวชาญ
</p>
</div>
<!-- Service 4 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
ติดตั้งระบบ
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
ทีมช่างผู้เชี่ยวชาญติดตั้งระบบท่อครบวงจร พร้อมรับประกันงาน
</p>
</div>
<!-- Service 5 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
จัดส่งสินค้า
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
บริการจัดส่งสินค้าทั่วประเทศ รวดเร็ว ปลอดภัย มีประกันความเสียหาย
</p>
</div>
<!-- Service 6 -->
<div class="group p-8 bg-secondary-50 rounded-2xl hover:bg-primary-600 transition-all duration-300 hover:shadow-xl">
<div class="w-16 h-16 bg-primary-600 text-white rounded-xl flex items-center justify-center mb-6 group-hover:bg-white group-hover:text-primary-600 transition-colors">
<svg class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
<h3 class="text-xl font-bold text-secondary-900 mb-3 group-hover:text-white transition-colors">
บริการหลังการขาย
</h3>
<p class="text-secondary-600 group-hover:text-primary-100 transition-colors">
ทีมงานพร้อมให้การดูแลและบริการซ่อมบำรุงหลังการขายตลอดอายุการใช้งาน
</p>
</div>
</div>
</div>
</section>
<!-- Process Section -->
<section class="py-20 bg-secondary-900">
<div class="container mx-auto px-4">
<div class="text-center mb-16">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">
ขั้นตอน<span class="text-primary-400">การทำงาน</span>
</h2>
<p class="text-secondary-300 text-lg max-w-2xl mx-auto">
เราให้ความสำคัญกับทุกขั้นตอน เพื่อให้ลูกค้าได้รับบริการที่ดีที่สุด
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Step 1 -->
<div class="relative">
<div class="text-center">
<span class="text-6xl font-bold text-primary-600/30">01</span>
<h3 class="text-xl font-bold text-white mt-4 mb-2">ปรึกษา</h3>
<p class="text-secondary-400">ติดต่อเราเพื่อปรึกษาเกี่ยวกับความต้องการของโครงการ</p>
</div>
</div>
<!-- Step 2 -->
<div class="relative">
<div class="text-center">
<span class="text-6xl font-bold text-primary-600/30">02</span>
<h3 class="text-xl font-bold text-white mt-4 mb-2">ออกแบบ</h3>
<p class="text-secondary-400">ทีมวิศวกรออกแบบระบบให้เหมาะสมกับการใช้งาน</p>
</div>
</div>
<!-- Step 3 -->
<div class="relative">
<div class="text-center">
<span class="text-6xl font-bold text-primary-600/30">03</span>
<h3 class="text-xl font-bold text-white mt-4 mb-2">เสนอราคา</h3>
<p class="text-secondary-400">เสนอราคาสินค้าและบริการอย่างโปร่งใส</p>
</div>
</div>
<!-- Step 4 -->
<div class="relative">
<div class="text-center">
<span class="text-6xl font-bold text-primary-600/30">04</span>
<h3 class="text-xl font-bold text-white mt-4 mb-2">ติดตั้ง</h3>
<p class="text-secondary-400">ทีมช่างติดตั้งโดยมืออาชีพตรงตามกำหนด</p>
</div>
</div>
</div>
</div>
</section>
<!-- Why Choose Us -->
<section class="py-20 bg-secondary-50">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h2 class="text-3xl md:text-4xl font-bold text-secondary-900 mb-6">
ทำไมต้องเลือก<span class="text-primary-600">ดีลพลัสเทค</span>
</h2>
<div class="space-y-6">
<div class="flex gap-4">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 class="font-bold text-secondary-900 mb-1">ประสบการณ์กว่า 10 ปี</h3>
<p class="text-secondary-600">เชี่ยวชาญด้านระบบท่อและอุปกรณ์ครบวงจร</p>
</div>
</div>
<div class="flex gap-4">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 class="font-bold text-secondary-900 mb-1">สินค้าคุณภาพ</h3>
<p class="text-secondary-600">สินค้าผ่านมาตรฐาน มอก. / FM / UL พร้อมรับประกัน</p>
</div>
</div>
<div class="flex gap-4">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 class="font-bold text-secondary-900 mb-1">ทีมงานมืออาชีพ</h3>
<p class="text-secondary-600">วิศวกรและช่างผู้เชี่ยวชาญพร้อมให้คำปรึกษา</p>
</div>
</div>
<div class="flex gap-4">
<div class="w-12 h-12 bg-primary-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<h3 class="font-bold text-secondary-900 mb-1">บริการรวดเร็ว</h3>
<p class="text-secondary-600">จัดส่งสินค้าทั่วประเทศ ตรงตามกำหนด</p>
</div>
</div>
</div>
</div>
<div class="relative aspect-video bg-secondary-200 rounded-2xl overflow-hidden">
<img
src="/images/2021/03/hdpe-welding_000C-1.jpg"
alt="ทีมงานมืออาชีพ"
class="object-cover w-full h-full"
loading="lazy"
/>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="py-20 bg-primary-600">
<div class="container mx-auto px-4 text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">
พร้อมเริ่มโครงการของคุณ?
</h2>
<p class="text-primary-100 text-lg mb-8 max-w-">
ต2xl mx-autoิดต่อเราวันนี้เพื่อรับคำปรึกษาและใบเสนอราคาฟรี
</p>
<div class="flex flex-wrap justify-center gap-4">
<a href="/contact-us/" class="btn-secondary bg-white text-primary-600 hover:bg-primary-50">
ติดต่อเรา
</a>
<a href="tel:090-555-1415" class="btn-outline border-white text-white hover:bg-white hover:text-primary-600">
โทร: 090-555-1415
</a>
</div>
</div>
</section>
</main>
<FloatingContact />
</BaseLayout>

View File

@@ -0,0 +1,130 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="ข้อกำหนดและเงื่อนไข"
description="ข้อกำหนดและเงื่อนไขการใช้งานเว็บไซต์ของบริษัท ดีล พลัส เทค จำกัด"
>
<main class="min-h-screen bg-secondary-50">
<div class="container mx-auto px-4 py-12">
<div class="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-8 md:p-12">
<h1 class="text-4xl font-bold text-secondary-900 mb-4">ข้อกำหนดและเงื่อนไข</h1>
<p class="text-secondary-600 mb-8">Terms and Conditions - มีผลบังคับใช้ตั้งแต่วันที่ 9 มีนาคม 2026</p>
<div class="prose prose-lg max-w-none text-secondary-700">
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">1. การยอมรับข้อกำหนด</h2>
<p class="mb-4">
ยินดีต้อนรับสู่เว็บไซต์ของ <strong>บริษัท ดีล พลัส เทค จำกัด</strong> ("เรา", "ของเรา" หรือ "เว็บไซต์")
โดยการเข้าใช้งานเว็บไซต์นี้ ท่านยอมรับว่าท่านได้อ่าน เข้าใจ และตกลงที่จะผูกพันกับข้อกำหนดและเงื่อนไขเหล่านี้
หากท่านไม่ยอมรับข้อกำหนดใด ๆ กรุณาหยุดการใช้งานเว็บไซต์นี้
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">2. คำอธิบายบริการ</h2>
<p class="mb-4">
เว็บไซต์นี้ให้บริการข้อมูลเกี่ยวกับสินค้าและบริการของเรา รวมถึง:
</p>
<ul class="list-disc pl-6 space-y-2">
<li>ข้อมูลผลิตภัณฑ์ท่อและอุปกรณ์ระบบ HVAC</li>
<li>ข้อมูลทางเทคนิคและสเปคสินค้า</li>
<li>บริการให้คำปรึกษา</li>
<li>ช่องทางการติดต่อและขอใบเสนอราคา</li>
</ul>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">3. สิทธิ์ในทรัพย์สินทางปัญญา</h2>
<p class="mb-4">
เนื้อหาทั้งหมดบนเว็บไซต์นี้ รวมถึงแต่ไม่จำกัดเพียง ข้อความ รูปภาพ กราฟิก โลโก้ ไอคอน
และซอฟต์แวร์ เป็นทรัพย์สินทางปัญญาของบริษัท ดีล พลัส เทค จำกัด และได้รับความคุ้มครองตามกฎหมายลิขสิทธิ์
ห้ามมิให้ทำซ้ำ ดัดแปลง เผยแพร่ หรือใช้เพื่อการค้าโดยไม่ได้รับอนุญาตเป็นลายลักษณ์อักษร
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">4. ข้อผูกมัดของผู้ใช้</h2>
<p class="mb-4">ท่านตกลงที่จะ:</p>
<ul class="list-disc pl-6 space-y-2">
<li>ใช้เว็บไซต์นี้เพื่อวัตถุประสงค์ที่ถูกต้องตามกฎหมายเท่านั้น</li>
<li>ไม่ให้ข้อมูลที่เป็นเท็จหรือไม่ถูกต้อง</li>
<li>ไม่พยายามเข้าถึงระบบหรือข้อมูลโดยไม่ได้รับอนุญาต</li>
<li>ไม่ใช้เว็บไซต์ในทางที่ผิดหรือเป็นอันตรายต่อผู้อื่น</li>
<li>เคารพสิทธิ์ในทรัพย์สินทางปัญญาของเรา</li>
</ul>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">5. การจำกัดความรับผิด</h2>
<p class="mb-4">
เราพยายามให้ข้อมูลที่ถูกต้องและทันสมัยบนเว็บไซต์ อย่างไรก็ตาม เราไม่รับประกันว่า:
</p>
<ul class="list-disc pl-6 space-y-2">
<li>ข้อมูลบนเว็บไซต์จะถูกต้อง ครบถ้วน หรือเป็นปัจจุบันเสมอ</li>
<li>เว็บไซต์จะทำงานได้โดยไม่มีการขัดข้องหรือปราศจากข้อผิดพลาด</li>
<li>เว็บไซต์จะปลอดภัยจากการโจมตีทางไซเบอร์หรือไวรัส</li>
</ul>
<p class="mt-4">
เราจะไม่รับผิดชอบต่อความเสียหายใด ๆ ที่เกิดขึ้นจากการใช้หรือไม่สามารถใช้เว็บไซต์นี้
ไม่ว่ากรณีใด ๆ ทั้งสิ้น
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">6. เงื่อนไขการ终止</h2>
<p class="mb-4">
เราขอสงวนสิทธิ์ในการระงับหรือยกเลิกการเข้าถึงเว็บไซต์ของท่าน โดยไม่ต้องแจ้งให้ทราบล่วงหน้า
หาก我们发现ว่าท่านละเมิดข้อกำหนดและเงื่อนไขเหล่านี้
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">7. กฎหมายที่ใช้บังคับ</h2>
<p class="mb-4">
ข้อกำหนดและเงื่อนไขนี้ อยู่ภายใต้บังคับของกฎหมายแห่งราชอาณาจักรไทย
และให้ตีความตามกฎหมายดังกล่าว
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">8. การระงับข้อพิพาท</h2>
<p class="mb-4">
หากเกิดข้อพิพาทใด ๆ จากข้อกำหนดและเงื่อนไขนี้ คู่สัญญาตกลงที่จะเจรจาไกล่เกลี่ยข้อพิพาท
หากไม่สามารถตกลงกันได้ ให้อยู่ในอำนาจพิจารณาคดีของศาลไทย
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">9. การแก้ไขข้อกำหนด</h2>
<p class="mb-4">
เราขอสงวนสิทธิ์ในการแก้ไขข้อกำหนดและเงื่อนไขนี้เมื่อใดก็ได้
โดยจะแจ้งให้ท่านทราบผ่านการเผยแพร่บนเว็บไซต์ การแก้ไขจะมีผลบังคับใช้ทันทีหลังการเผยแพร่
กรุณาตรวจสอบหน้าทนี้เป็นระยะ
</p>
</section>
<section class="mb-8">
<h2 class="text-2xl font-bold text-secondary-900 mb-4">10. ข้อมูลการติดต่อ</h2>
<p class="mb-4">หากมีคำถามเกี่ยวกับข้อกำหนดและเงื่อนไขนี้ กรุณาติดต่อ:</p>
<div class="bg-secondary-50 p-4 rounded-lg">
<p><strong>บริษัท ดีล พลัส เทค จำกัด</strong></p>
<p>ที่อยู่: 9/70 ซอยนครลุง 17 แขวงบางไผ่ เขตบางแค กทม. 10160</p>
<p>โทรศัพท์: 090-555-1415</p>
<p>อีเมล: info@dealplustech.co.th</p>
</div>
</section>
<section class="mt-12 pt-8 border-t border-secondary-200">
<p class="text-sm text-secondary-600">
ข้อกำหนดและเงื่อนไขนี้เป็นส่วนหนึ่งของข้อตกลงการใช้งานเว็บไซต์ของเรา
และต้องอ่านร่วมกับ <a href="/privacy-policy/" class="text-primary-600 hover:underline">นโยบายความเป็นส่วนตัว</a>
และ <a href="/cookie-policy/" class="text-primary-600 hover:underline">นโยบายคุกกี้</a>
</p>
</section>
</div>
</div>
</div>
</main>
</BaseLayout>

157
src/styles/global.css Normal file
View File

@@ -0,0 +1,157 @@
@import "tailwindcss";
/* Deal Plus Tech - Industrial Theme */
@theme {
/* Primary Colors - Green for trust and growth */
--color-primary-50: #f0fdf4;
--color-primary-100: #dcfce7;
--color-primary-200: #bbf7d0;
--color-primary-300: #86efac;
--color-primary-400: #4ade80;
--color-primary-500: #22c55e;
--color-primary-600: #16a34a;
--color-primary-700: #15803d;
--color-primary-800: #166534;
--color-primary-900: #14532d;
/* Secondary Colors - Slate grays for industrial look */
--color-secondary-50: #f8fafc;
--color-secondary-100: #f1f5f9;
--color-secondary-200: #e2e8f0;
--color-secondary-300: #cbd5e1;
--color-secondary-400: #94a3b8;
--color-secondary-500: #64748b;
--color-secondary-600: #475569;
--color-secondary-700: #334155;
--color-secondary-800: #1e293b;
--color-secondary-900: #0f172a;
/* Accent Colors - Yellow for highlights */
--color-accent-400: #facc15;
--color-accent-500: #eab308;
--color-accent-600: #ca8a04;
/* Industrial custom colors */
--color-industrial-dark: #1a1a1a;
--color-industrial-light: #f5f5f5;
/* Font - Kanit for Thai support */
--font-sans: 'Kanit', system-ui, sans-serif;
--font-mono: ui-monospace, monospace;
/* Shadows */
--shadow-card: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-industrial: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--shadow-bold: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}
@layer base {
html {
scroll-behavior: smooth;
/* Base font size */
font-size: 16px;
}
/* Responsive font sizes for larger screens */
@media (min-width: 1280px) {
html {
font-size: 18px;
}
}
@media (min-width: 1536px) {
html {
font-size: 20px;
}
}
@media (min-width: 1920px) {
html {
font-size: 22px;
}
}
@media (min-width: 2560px) {
html {
font-size: 24px;
}
}
body {
@apply bg-white text-secondary-900 antialiased;
}
h1, h2, h3, h4, h5, h6 {
@apply font-bold tracking-tight;
}
}
@layer components {
.btn-primary {
@apply inline-flex items-center justify-center px-6 py-3 md:px-8 md:py-4 bg-primary-600 text-white font-semibold rounded-lg
hover:bg-primary-700 transition-all duration-200 shadow-bold hover:shadow-industrial
active:translate-y-0.5 text-base md:text-lg;
}
.btn-secondary {
@apply inline-flex items-center justify-center px-6 py-3 md:px-8 md:py-4 bg-secondary-800 text-white font-semibold rounded-lg
hover:bg-secondary-900 transition-all duration-200 text-base md:text-lg;
}
.btn-outline {
@apply inline-flex items-center justify-center px-6 py-3 md:px-8 md:py-4 border-2 border-primary-600 text-primary-600 font-semibold rounded-lg
hover:bg-primary-600 hover:text-white transition-all duration-200 text-base md:text-lg;
}
.section-title {
@apply text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold text-secondary-900;
}
.section-subtitle {
@apply text-lg md:text-xl lg:text-2xl xl:text-3xl text-secondary-600 mt-4;
}
.card {
@apply bg-white rounded-xl shadow-card overflow-hidden transition-all duration-300
hover:shadow-industrial hover:-translate-y-1;
}
.card-industrial {
@apply bg-secondary-800 text-white rounded-xl p-6 border-l-4 border-primary-500;
}
.gradient-overlay {
@apply absolute inset-0 bg-gradient-to-r from-industrial-dark/90 to-industrial-dark/70;
}
.industrial-badge {
@apply inline-flex items-center px-3 py-1 md:px-4 md:py-2 bg-primary-600 text-white text-sm md:text-base font-semibold rounded;
}
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
.text-gradient {
@apply bg-clip-text text-transparent bg-gradient-to-r from-primary-500 to-primary-700;
}
/* Responsive text utilities */
.text-responsive-sm {
@apply text-sm md:text-base lg:text-lg xl:text-xl;
}
.text-responsive-base {
@apply text-base md:text-lg lg:text-xl xl:text-2xl;
}
.text-responsive-lg {
@apply text-lg md:text-xl lg:text-2xl xl:text-3xl;
}
.text-responsive-xl {
@apply text-xl md:text-2xl lg:text-3xl xl:text-4xl;
}
}

View File

@@ -1,77 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
html {
scroll-behavior: smooth;
}
body {
@apply bg-white text-secondary-900 antialiased;
}
h1, h2, h3, h4, h5, h6 {
@apply font-bold tracking-tight;
}
}
@layer components {
.btn-primary {
@apply inline-flex items-center justify-center px-6 py-3 bg-primary-600 text-white font-semibold rounded-lg
hover:bg-primary-700 transition-all duration-200 shadow-bold hover:shadow-industrial
active:translate-y-0.5;
}
.btn-secondary {
@apply inline-flex items-center justify-center px-6 py-3 bg-secondary-800 text-white font-semibold rounded-lg
hover:bg-secondary-900 transition-all duration-200;
}
.btn-outline {
@apply inline-flex items-center justify-center px-6 py-3 border-2 border-primary-600 text-primary-600 font-semibold rounded-lg
hover:bg-primary-600 hover:text-white transition-all duration-200;
}
.section-title {
@apply text-3xl md:text-4xl lg:text-5xl font-bold text-secondary-900;
}
.section-subtitle {
@apply text-lg md:text-xl text-secondary-600 mt-4;
}
.card {
@apply bg-white rounded-xl shadow-card overflow-hidden transition-all duration-300
hover:shadow-industrial hover:-translate-y-1;
}
.card-industrial {
@apply bg-secondary-800 text-white rounded-xl p-6 border-l-4 border-primary-500;
}
.gradient-overlay {
@apply absolute inset-0 bg-gradient-to-r from-industrial-dark/90 to-industrial-dark/70;
}
.industrial-badge {
@apply inline-flex items-center px-3 py-1 bg-primary-600 text-white text-sm font-semibold rounded;
}
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
.text-gradient {
@apply bg-clip-text text-transparent bg-gradient-to-r from-primary-500 to-primary-700;
}
}
/*
* Typography Best Practices:
* - Use .text-base (16px) as minimum for readable text
* - Avoid .text-xs (12px) and .text-sm (14px) for body content
* - For less emphasis, use color (text-secondary-600) not smaller size
*/

View File

@@ -1,133 +0,0 @@
// Site Configuration Types
export interface SiteConfig {
name: string;
nameTh: string;
url: string;
description: string;
phone: string;
email: string;
lineId: string;
facebookUrl: string;
address: string;
}
export interface WorkHours {
day: string;
hours: string;
isClosed?: boolean;
}
export interface ProductCategory {
id: string;
name: string;
nameEn: string;
slug: string;
href: string;
image: string;
description: string;
shortDescription?: string;
keywords?: string[];
// Enhanced SEO Content
seoContent?: string;
// Product Specifications
specifications?: ProductSpecification[];
// Key Features
features?: string[];
// Applications/Uses
applications?: string[];
// Standards & Certifications
certifications?: string[];
// FAQ Section
faq?: FAQItem[];
// Schema.org data
schemaData?: {
brand?: string;
manufacturer?: string;
sku?: string;
mpn?: string;
material?: string;
category?: string;
};
// Related product IDs
relatedProductIds?: string[];
// Product Tables (extracted from images)
productTables?: ProductTable[];
}
export interface ProductSpecification {
label: string;
value: string;
unit?: string;
}
export interface FAQItem {
question: string;
answer: string;
}
export interface ProductTable {
tableName: string;
headers: string[];
rows: string[][];
}
export interface NavItem {
label: string;
labelEn: string;
href: string;
children?: NavItem[];
}
// Blog Types
export interface BlogPost {
slug: string;
title: string;
excerpt: string;
content: string;
date: string;
author: string;
category: string;
image?: string;
}
export interface BlogCategory {
name: string;
slug: string;
count: number;
}
// Portfolio Types
export interface PortfolioItem {
id: string;
title: string;
category: string;
image: string;
description: string;
}
export interface PortfolioProject {
id: string;
name: string;
href: string;
image: string;
description: string;
}
// Contact Form Types
export interface ContactFormData {
name: string;
email: string;
phone: string;
subject: string;
message: string;
}
// SEO Types
export interface SEOData {
title: string;
description: string;
keywords?: string[];
ogImage?: string;
canonical?: string;
}