feat: light theme page templates + integration with new content collections

- All 11 page templates rewritten for light theme
- index.astro: 8 sections (hero, stats yellow band, problem cards,
  services mega-grid, black pull-quote, blog preview, yellow CTA)
- about.astro: story + values (4 dark-icon cards) + process 4-step
- contact.astro: 4 channel picker cards + 8-field form (added budget field)
  + 3-step 'what happens next' + pre-submit FAQ + yellow final CTA
- faq.astro: dynamic category rendering from content/faq collection
  (5 categories, 20 Q&A) + tag cloud + 3 channel cards
- portfolio.astro: industry filter bar (sticky) + 9 items with new
  schema (industry, what_we_did, result fields) + 'ดีลที่เราเลือก' section
- services/index.astro: decision table (6 rows, scannable in 30s)
  + 3 pricing tiers (Starter/Business/Enterprise) + add-on chips
- services/[slug].astro: 4 service types with light hero + pricing +
  tech options + AI features + 6-FAQ per service
- blog/index.astro: featured + 4-card grid from content collection
- blog/[slug].astro: 2-column with sidebar (about, contact, related)
- privacy.astro + terms.astro: legal content, light theme
- All form posts go to setTimeout success (placeholder for backend wire)
This commit is contained in:
Macky
2026-06-03 14:15:33 +07:00
parent 00b0de2d9a
commit 0855e3d77b
11 changed files with 2311 additions and 4363 deletions

View File

@@ -3,89 +3,115 @@ import Base from '../layouts/Base.astro';
import Navigation from '../components/Navigation.astro';
import Footer from '../components/Footer.astro';
import PageHero from '../components/PageHero.astro';
import { getCollection } from 'astro:content';
const faqData = [
{
category: "บริการ",
icon: "🎯",
items: [
{ q: "บริการของเรามีอะไรบ้าง?", a: "เราให้บริการ รับทำเว็บไซต์, Marketing Automation, AI Automation และ Technology Consult สำหรับธุรกิจไทย" },
{ q: "สามารถปรับแต่งงานตามความต้องการได้ไหม?", a: "ใช่! เราออกแบบโซลูชันที่เหมาะกับความต้องการเฉพาะของแต่ละธุรกิจ" },
]
},
{
category: "ราคา",
icon: "💰",
items: [
{ q: "ราคาเริ่มต้นเท่าไหร่?", a: "ราคาขึ้นอยู่กับความต้องการและขอบเขตของโปรเจกต์ ติดต่อเราเพื่อรับใบเสนอราคาฟรี" },
{ q: "มี package สำเร็จรูปไหม?", a: "มี เรามี package สำหรับลูกค้าที่ต้องการโซลูชันที่ครบถ้วนและราคาคุ้มค่า" },
]
},
{
category: "ระยะเวลา",
icon: "⏱️",
items: [
{ q: "ใช้เวลาพัฒนานานแค่ไหน?", a: "ขึ้นอยู่กับความซับซ้อนของโปรเจกต์ เว็บไซต์มาตรฐาน 2-4 สัปดาห์, ระบบซับซ้อนอาจใช้ 1-3 เดือน" },
]
},
{
category: "ทั่วไป",
icon: "💬",
items: [
{ q: "มีการรับประกันผลงานไหม?", a: "เรารับประกันคุณภาพ หากไม่พอใจเราพร้อมแก้ไขจนกว่าจะถูกใจ" },
{ q: "หลังส่งมอบงานแล้วมี after service ไหม?", a: "มี เราให้บริการดูแลและ support หลังการขายตลอด 24 ชม." },
]
},
];
const faqItems = await getCollection('faq');
const categories = ['บริการ', 'ราคา', 'ระยะเวลา', 'AI & เทคนิค', 'หลังการขาย'];
const categoryIcons: Record<string, string> = {
'บริการ': '💼',
'ราคา': '💰',
'ระยะเวลา': '⏱️',
'AI & เทคนิค': '🤖',
'หลังการขาย': '🛠️',
};
---
<Base title="คำถามที่พบบ่อย | MoreminiMore - รับทำเว็บไซต์ SEO AI Chatbot">
<Base title="คำถามที่พบบ่อย | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<Navigation />
<PageHero
<PageHero
badge="FAQ"
title="คำถามที่พบบ่อย"
subtitle="หาคำตอบสำหรับคำถามที่พบบ่อยเกี่ยวกับบริการของเรา"
title="คำถามที่ลูกค้าถามบ่อยที่สุด"
subtitle="30+ คำถามที่รวบรวมจากแชต LINE จริง ๆ ไม่ใช่แต่งขึ้นเอง"
/>
<!-- FAQ Section -->
<section class="section faq-section">
<div class="container">
<div class="faq-content">
{faqData.map(cat => (
{categories.map(cat => {
const items = faqItems.filter(f => f.data.category === cat);
if (items.length === 0) return null;
return (
<div class="faq-category">
<h2 class="category-title">
<span class="category-icon">{cat.icon}</span>
{cat.category}
<span class="category-icon">{categoryIcons[cat]}</span>
{cat}
</h2>
<div class="faq-list">
{cat.items.map((item, qIndex) => (
<div class="faq-item" data-item={qIndex}>
<button class="faq-question" aria-expanded="false">
<span class="question-text">{item.q}</span>
<span class="faq-icon">+</span>
</button>
{items.map((item, qIndex) => (
<details class="faq-item">
<summary class="faq-question">
<span class="question-text">{item.data.question}</span>
<span class="faq-toggle">+</span>
</summary>
<div class="faq-answer">
<p>{item.a}</p>
<p>{item.data.answer}</p>
</div>
</div>
</details>
))}
</div>
</div>
))}
);
})}
<!-- Other Topics -->
<div class="faq-category">
<h2 class="category-title">
<span class="category-icon">📚</span>
เรื่องอื่น ๆ ที่ลูกค้าถามบ่อย
</h2>
<div class="tag-cloud">
<span class="topic-tag">โฮสติ้ง</span>
<span class="topic-tag">โดเมน</span>
<span class="topic-tag">SSL</span>
<span class="topic-tag">ใบเสนอราคา</span>
<span class="topic-tag">ใบกำกับภาษี</span>
<span class="topic-tag">สัญญา</span>
<span class="topic-tag">NDA</span>
<span class="topic-tag">ลิขสิทธิ์งาน</span>
<span class="topic-tag">ทีมงาน</span>
<span class="topic-tag">ขนาดทีม</span>
<span class="topic-tag">ที่ตั้งบริษัท</span>
<span class="topic-tag">ตัวอย่างงาน</span>
<span class="topic-tag">ขอดูเว็บจริง</span>
<span class="topic-tag">นัดคุยนอกสถานที่</span>
</div>
</div>
<!-- Quick Channels -->
<div class="channels-section">
<h2 class="channels-title">ไม่เจอคำตอบ? ถามตรง ๆ เลย</h2>
<div class="channels-grid">
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="channel-card">
<div class="channel-icon">💬</div>
<h3 class="channel-name">LINE</h3>
<p class="channel-handle">@moreminimore</p>
<p class="channel-time">ตอบใน 30 นาที (เวลาทำการ)</p>
</a>
<a href="tel:0809955945" class="channel-card">
<div class="channel-icon">📞</div>
<h3 class="channel-name">โทร</h3>
<p class="channel-handle">080-995-5945</p>
<p class="channel-time">จ-ศ 09:00-18:00</p>
</a>
<a href="mailto:contact@moreminimore.com" class="channel-card">
<div class="channel-icon">📧</div>
<h3 class="channel-name">Email</h3>
<p class="channel-handle">contact@moreminimore.com</p>
<p class="channel-time">ตอบภายใน 1 วัน</p>
</a>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="section section-primary cta-section">
<section class="section section-yellow cta-section">
<div class="container">
<div class="cta-content">
<h2 class="cta-title">ยังมีคำถามอื่น?</h2>
<p class="cta-desc">ติดต่อเราได้โดยตรง เราพร้อมตอบทุกคำถาม</p>
<h2 class="cta-title">พร้อมคุยรายละเอียด?</h2>
<p class="cta-desc">นัดปรึกษาฟรี 30 นาที ผ่าน Zoom หรือนัดเจอที่ออฟฟิศ (กรุงเทพ/สมุทรสาคร)</p>
<div class="cta-actions">
<a href="/contact" class="btn btn-secondary btn-lg">ติดต่อเรา</a>
<a href="tel:0809955945" class="btn btn-outline-dark btn-lg">080-995-5945</a>
<a href="/contact" class="btn btn-dark btn-lg">นัดปรึกษา →</a>
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-outline-dark btn-lg">ทัก LINE ตอนนี้</a>
</div>
</div>
</div>
@@ -94,116 +120,183 @@ const faqData = [
<Footer />
</Base>
<script>
document.addEventListener('DOMContentLoaded', () => {
const faqItems = document.querySelectorAll('.faq-item');
faqItems.forEach(item => {
const question = item.querySelector('.faq-question');
const answer = item.querySelector('.faq-answer');
const icon = item.querySelector('.faq-icon');
question?.addEventListener('click', () => {
const isOpen = item.classList.contains('open');
faqItems.forEach(faq => {
faq.classList.remove('open');
const fa = faq.querySelector('.faq-answer') as HTMLElement;
const fi = faq.querySelector('.faq-icon');
if (fa) fa.style.maxHeight = '0';
if (fi) fi.textContent = '+';
(faq.querySelector('.faq-question') as HTMLElement)?.setAttribute('aria-expanded', 'false');
});
if (!isOpen) {
item.classList.add('open');
if (answer) (answer as HTMLElement).style.maxHeight = answer.scrollHeight + 'px';
if (icon) icon.textContent = '';
if (question) (question as HTMLElement).setAttribute('aria-expanded', 'true');
}
});
});
});
</script>
<style>
.faq-section { background: var(--color-white); }
.faq-content { max-width: 800px; margin: 0 auto; }
.faq-category { margin-bottom: 60px; }
.section-yellow { background: var(--color-primary); }
.faq-category {
max-width: 800px;
margin: 0 auto 60px;
}
.category-title {
display: flex;
align-items: center;
gap: 12px;
font-size: 24px;
font-weight: 700;
font-family: var(--font-display);
font-size: 22px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 2px solid var(--color-primary);
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 3px solid var(--color-primary);
}
.category-icon { font-size: 28px; }
.faq-list { display: flex; flex-direction: column; gap: 12px; }
.faq-item {
background: var(--color-white);
border-radius: 12px;
border-radius: var(--radius-md);
border: 1px solid var(--color-gray-200);
overflow: hidden;
border: 1px solid rgba(0,0,0,0.08);
transition: all 0.3s;
transition: all 0.3s ease;
}
.faq-item:hover { box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
.faq-item.open { border-color: var(--color-primary); }
.faq-item[open] { border-color: var(--color-primary); }
.faq-item:hover { box-shadow: var(--shadow-sm); }
.faq-question {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 24px;
background: none;
border: none;
cursor: pointer;
text-align: left;
font-family: var(--font-heading);
list-style: none;
transition: background 0.2s ease;
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question:hover { background: var(--color-bg-alt); }
.question-text {
flex: 1;
font-family: var(--font-display);
font-size: 16px;
font-weight: 600;
font-weight: 700;
color: var(--color-black);
padding-right: 16px;
}
.question-text { flex: 1; padding-right: 16px; }
.faq-icon {
font-size: 24px;
color: var(--color-primary);
.faq-toggle {
font-size: 28px;
font-weight: 300;
transition: transform 0.3s;
color: var(--color-primary);
flex-shrink: 0;
line-height: 1;
}
.faq-answer { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; }
.faq-answer p {
.faq-item[open] .faq-toggle { transform: rotate(45deg); }
.faq-answer {
padding: 0 24px 24px;
}
.faq-answer p {
font-size: 15px;
line-height: 1.8;
color: #555;
color: var(--color-gray-700);
white-space: pre-line;
}
.section-primary { background: var(--color-primary); }
.cta-content { text-align: center; }
.cta-title {
font-size: clamp(28px, 4vw, 42px);
font-weight: 800;
margin-bottom: 16px;
/* Tag cloud */
.tag-cloud {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.topic-tag {
display: inline-block;
padding: 8px 16px;
background: var(--color-bg-alt);
color: var(--color-gray-700);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-full);
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
}
.topic-tag:hover {
background: var(--color-primary);
border-color: var(--color-primary);
color: var(--color-black);
}
/* Channels */
.channels-section {
max-width: 900px;
margin: 80px auto 0;
padding: 60px 40px;
background: var(--color-bg-alt);
border-radius: var(--radius-xl);
text-align: center;
}
.channels-title {
font-family: var(--font-display);
font-size: 28px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 32px;
}
.channels-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.channel-card {
display: block;
background: var(--color-white);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-lg);
padding: 24px;
text-align: center;
transition: all 0.3s ease;
}
.channel-card:hover {
border-color: var(--color-primary);
transform: translateY(-4px);
box-shadow: var(--shadow-md);
}
.channel-icon { font-size: 32px; margin-bottom: 12px; }
.channel-name {
font-family: var(--font-display);
font-size: 18px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 4px;
}
.channel-handle {
font-size: 14px;
font-weight: 700;
color: var(--color-primary-dark);
margin-bottom: 4px;
}
.channel-time {
font-size: 12px;
color: var(--color-gray-500);
}
/* CTA */
.cta-content { text-align: center; max-width: 700px; margin: 0 auto; }
.cta-title {
font-family: var(--font-display);
font-size: clamp(28px, 4vw, 44px);
font-weight: 900;
color: var(--color-black);
margin-bottom: 16px;
}
.cta-desc {
font-size: 18px;
color: rgba(0,0,0,0.7);
color: rgba(0, 0, 0, 0.7);
margin-bottom: 32px;
}
.cta-actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
.btn-outline-dark {
background: transparent;
color: var(--color-black);
border: 2px solid var(--color-black);
.cta-actions {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
}
.btn-outline-dark:hover { background: var(--color-black); color: var(--color-white); }
.btn-lg { padding: 16px 36px; font-size: 16px; }
@media (max-width: 640px) {
.faq-question { padding: 16px 20px; font-size: 15px; }
.faq-answer p { padding: 0 20px 20px; }
.cta-actions { flex-direction: column; }
.btn-lg { width: 100%; justify-content: center; }
@media (max-width: 1024px) {
.channels-grid { grid-template-columns: 1fr; }
}
</style>
@media (max-width: 640px) {
.cta-actions { flex-direction: column; }
.cta-actions .btn { width: 100%; justify-content: center; }
.faq-question { padding: 16px 20px; }
.question-text { font-size: 15px; }
}
</style>