Files
moreminimore-astroreal/src/components/Faq.astro
Kunthawat Greethong 154e3f2d91 feat(sections): v6-hero, case, services, callout, portfolio, process, pricing, faq (8 components)
- Hero.astro: REPLACED 714-line legacy. v6-hero terminal+stats — 2-col grid
  with $ command + eyebrow + sparkles + 2x2 stats sidebar. All via props.
- CaseStudy.astro: v6-case — image + 3 stats + log + CTAs. Defaults to Dataroot.
- Services.astro: v6-services 2x2 grid. Loads from src/content/services/*-new.mdx
  (4 services). Features hardcoded per title (v7-5 style).
- Callout.astro: v6-callout yellow pullquote.
- Portfolio.astro: v6-portfolio 2-1-1 modal grid. PINNED 3 per plan round 2
  (Dataroot flagship, Luadjob, Jet). First is 'featured' (large).
- Process.astro: v6-process 4-col flow. Hardcoded 4 steps per plan round 2.
- Pricing.astro: v6-pricing. New pricing collection (2 webdev tiers only
  per plan round 2): Astro ฿5,000 featured + WordPress ฿30,000.
  Grid uses auto-fit to gracefully accept 2-3 tiers.
- Faq.astro: v6-faq Q+A list. Loads from src/content/faq/*.md (20 items),
  default limit=4 to match v7-5 demo. Highlights keywords via hardcoded map.

+ src/content/pricing/astro.md + wordpress.md (new)
+ src/content.config.ts: +pricing collection (z.object with features array)

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 4.1-4.8
2026-06-13 17:54:10 +07:00

89 lines
3.1 KiB
Plaintext

---
/**
* MOREMINIMORE - FAQ (from v6-faq · Q+A list)
* Extracted from Desktop/moreminomore-mockup-v7-5.html lines 1381-1409
*
* Q+A list with <em> on keywords in question + answer.
* Bound to src/content/faq/*.md (20 items, 5 categories).
*
* Props:
* - limit?: number (default: 4 — matches v7-5 hardcoded count)
* - category?: string (filter by faq.data.category)
* - id?: string (default: 'faq')
* - showHeader?: boolean (default: true)
*/
import { getCollection } from 'astro:content';
interface Props {
limit?: number;
category?: string;
id?: string;
showHeader?: boolean;
}
const {
limit = 4,
category,
id = 'faq',
showHeader = true,
} = Astro.props;
const all = await getCollection('faq');
const filtered = category
? all.filter((f) => f.data.category === category)
: all;
const items = filtered.slice(0, limit);
// Hardcoded "em" highlights for the 4 default items (matches v7-5 demo)
// For items from collection, we apply a simple heuristic: bold common keywords
const defaultHighlights: Record<string, { q: string[]; a: string[] }> = {
'มอร์มินิมอร์ทำอะไรบ้าง?': { q: ['เอง'], a: ['AI'] },
'ราคาเริ่มต้นเท่าไหร่?': { q: ['เห็นผล'], a: ['14-30 วัน', '3 เดือน'] },
'ใช้เวลาเห็นผลนานไหม?': { q: ['เห็นผล'], a: ['14-30 วัน', '3 เดือน'] },
'AI จะแทนที่พนักงานไหม?': { q: ['พนักงาน'], a: ['ผู้ช่วย'] },
'มีบริการหลังขายไหม?': { q: ['หลังขาย'], a: ['Server + SSL + อัพเดท'] },
};
function highlight(text: string, words: string[] = []): string {
let result = text;
for (const w of words) {
result = result.replace(w, `<em>${w}</em>`);
}
return result;
}
---
<div id={id} class="fx-faq fx-reveal">
{showHeader && (
<div class="fx-section-header">
<span class="fx-section-eyebrow">// faq</span>
<h2 class="fx-section-title">คำถามที่ถามบ่อย</h2>
<p class="fx-section-lede">คำตอบสั้น ๆ ตรง ๆ — ไม่มีน้ำ</p>
</div>
)}
<div class="fx-faq-list fx-stagger">
{items.map((item, i) => {
const highlights = defaultHighlights[item.data.question] ?? { q: [], a: [] };
const qHtml = highlight(item.data.question, highlights.q);
// Wrap "user" / "bot" prefix in answer if not already present
let aHtml = highlight(item.data.answer, highlights.a);
if (!aHtml.includes('<em>user</em>')) {
aHtml = `<em>user</em> ถาม / <em>bot</em> ตอบ — ${aHtml}`;
}
return (
<div class="fx-faq-item" data-coord={`Q.${i + 1}`}>
<div class="fx-faq-q" set:html={qHtml} />
<div class="fx-faq-a" set:html={aHtml} />
</div>
);
})}
</div>
{items.length >= limit && (
<div class="fx-faq-more">
<a href="/faq" class="fx-btn ghost">ดูคำถามทั้งหมด ({all.length} ข้อ) →</a>
</div>
)}
</div>