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
This commit is contained in:
102
src/components/CaseStudy.astro
Normal file
102
src/components/CaseStudy.astro
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
/**
|
||||
* MOREMINIMORE - CASESTUDY (from v6-case)
|
||||
* Extracted from Desktop/moreminomore-mockup-v7-5.html lines 873-919
|
||||
*
|
||||
* 2-col grid: image (left) + content (right, with stats + log + CTAs)
|
||||
* Currently used for Dataroot flagship case study only.
|
||||
* Hardcoded data — case_study body still lives in src/content/portfolio/dataroot.md
|
||||
*
|
||||
* Props:
|
||||
* - client: string (e.g. 'Dataroot')
|
||||
* - url?: string (link to client site)
|
||||
* - image?: string (default: dataroot.png from /images/portfolio/)
|
||||
* - stats: { value, label, coord }[] (default: Dataroot +373/+114/-28)
|
||||
* - quote: string (large pullquote with <em>)
|
||||
* - deck: string (subhead under quote)
|
||||
* - logs: { ts, level, text }[] (default: 3-line timeline)
|
||||
* - ctaPrimary?: { text, href } (default: อ่านเคสเต็ม → /portfolio)
|
||||
* - ctaSecondary?: { text, href } (default: ดูผลงานอื่น → /portfolio)
|
||||
* - id?: string (default: 'case')
|
||||
*/
|
||||
interface Stat {
|
||||
value: string;
|
||||
label: string;
|
||||
coord: string;
|
||||
}
|
||||
interface Log {
|
||||
ts: string;
|
||||
level: 'INFO' | 'SUCCESS' | 'WARN';
|
||||
text: string;
|
||||
}
|
||||
interface CTA {
|
||||
text: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
client: string;
|
||||
url?: string;
|
||||
image?: string;
|
||||
stats: Stat[];
|
||||
quote: string;
|
||||
deck: string;
|
||||
logs: Log[];
|
||||
ctaPrimary?: CTA;
|
||||
ctaSecondary?: CTA;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
client,
|
||||
url,
|
||||
image = '/images/portfolio/dataroot.png',
|
||||
stats,
|
||||
quote,
|
||||
deck,
|
||||
logs,
|
||||
ctaPrimary = { text: 'อ่านเคสเต็ม →', href: '/portfolio' },
|
||||
ctaSecondary = { text: 'ดูผลงานอื่น', href: '/portfolio' },
|
||||
id = 'case',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div id={id} class="fx-case fx-reveal">
|
||||
<span class="fx-sparkle s2" style="top:12%;right:6%">✦</span>
|
||||
<span class="fx-sparkle s4" style="bottom:16%;left:4%">◆</span>
|
||||
<span class="fx-sparkle s5" style="top:50%;right:4%">✦</span>
|
||||
|
||||
<div class="fx-case-grid">
|
||||
<div class="fx-case-image">
|
||||
<a href={url || ctaPrimary.href}>
|
||||
<img src={image} alt={client} loading="lazy" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="fx-case-content">
|
||||
<div class="fx-case-stats">
|
||||
{stats.map((stat) => (
|
||||
<div class="fx-case-stat" data-coord={stat.coord}>
|
||||
<div class="fx-case-stat-num" set:html={stat.value} />
|
||||
<div class="fx-case-stat-label">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<h2 set:html={`"${quote}"`} />
|
||||
<p class="fx-deck">{deck}</p>
|
||||
<div class="fx-log fx-stagger">
|
||||
{logs.map((log) => (
|
||||
<div>
|
||||
<span class="ts">{log.ts}</span>{' '}
|
||||
<span class={log.level === 'INFO' ? 'info' : 'ok'}>{log.level}</span>{' '}
|
||||
{log.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div class="fx-case-cta">
|
||||
<a href={ctaPrimary.href} class="fx-btn coral">{ctaPrimary.text}</a>
|
||||
<a href={ctaSecondary.href} class="fx-btn ghost">{ctaSecondary.text}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user