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

@@ -5,17 +5,22 @@ import Footer from '../../components/Footer.astro';
import PageHero from '../../components/PageHero.astro';
import { getCollection, render } from 'astro:content';
// For SSR mode, use Astro.params directly
const { slug } = Astro.params;
const allPosts = await getCollection('blog');
// Use id for matching since slug might be undefined
const post = allPosts.find(p => p.id === slug);
if (!post) {
return Astro.redirect('/404');
}
export async function getStaticPaths() {
const allPosts = await getCollection('blog');
return allPosts.map(post => ({
params: { slug: post.id },
props: { post },
}));
}
const { Content } = await render(post);
const related = allPosts
@@ -33,13 +38,12 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
<Base title={`${post.data.title} | MoreminiMore`}>
<Navigation />
<PageHero
<PageHero
badge={post.data.category}
title={post.data.title}
subtitle={formattedDate}
/>
<!-- Article Image -->
{post.data.image && (
<div class="article-image">
<div class="container">
@@ -48,7 +52,6 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
</div>
)}
<!-- Article Content -->
<section class="section article-section">
<div class="container">
<div class="article-grid">
@@ -57,27 +60,23 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
<Content />
</div>
</article>
<!-- Sidebar -->
<aside class="article-sidebar">
<!-- About -->
<div class="sidebar-card">
<h3 class="sidebar-title">เกี่ยวกับ MoreminiMore</h3>
<p class="sidebar-text">
ดิจิทัลเอเจนซี่ที่ช่วยให้ธุรกิจไทยเติบโตด้วยเทคโนโลยีสมัยใหม่
</p>
<a href="/about" class="btn btn-dark btn-sm">ดูเพิ่มเติม</a>
<a href="/about" class="btn btn-outline-dark btn-sm">ดูเพิ่มเติม</a>
</div>
<!-- Contact -->
<div class="sidebar-card">
<h3 class="sidebar-title">สนใจบริการ?</h3>
<p class="sidebar-text">ติดต่อเราได้เลย ปรึกษาฟรี!</p>
<a href="/contact" class="btn btn-primary btn-sm">ติดต่อเรา</a>
<a href="tel:0809955945" class="btn btn-outline btn-sm" style="margin-top: 8px;">080-995-5945</a>
<a href="tel:0809955945" class="btn btn-outline-dark btn-sm" style="margin-top: 8px;">080-995-5945</a>
</div>
<!-- Related Posts -->
{related.length > 0 && (
<div class="sidebar-card">
<h3 class="sidebar-title">บทความที่เกี่ยวข้อง</h3>
@@ -102,18 +101,16 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
<style>
.article-image {
padding: 40px 0;
background: var(--color-gray-100);
background: var(--color-bg-alt);
}
.article-image img {
width: 100%;
max-height: 500px;
object-fit: cover;
border-radius: 20px;
border-radius: var(--radius-xl);
}
.article-section {
padding-top: 60px;
}
.article-section { background: var(--color-white); }
.article-grid {
display: grid;
@@ -124,55 +121,42 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
.article-body {
font-size: 18px;
line-height: 1.8;
color: var(--color-gray-600);
color: var(--color-gray-700);
}
.article-body :global(h2) {
font-family: var(--font-display);
font-size: 28px;
font-weight: 700;
color: var(--color-dark);
font-weight: 800;
color: var(--color-black);
margin: 40px 0 20px;
}
.article-body :global(h3) {
font-family: var(--font-display);
font-size: 22px;
font-weight: 700;
color: var(--color-dark);
font-weight: 800;
color: var(--color-black);
margin: 32px 0 16px;
}
.article-body :global(p) {
margin-bottom: 20px;
}
.article-body :global(p) { margin-bottom: 20px; }
.article-body :global(ul), .article-body :global(ol) {
margin: 20px 0;
padding-left: 24px;
}
.article-body :global(li) {
margin-bottom: 12px;
}
.article-body :global(li) { margin-bottom: 12px; }
.article-body :global(a) {
color: var(--color-primary);
color: var(--color-primary-dark);
font-weight: 600;
}
.article-body :global(a:hover) {
text-decoration: underline;
}
.article-body :global(a:hover) { text-decoration: underline; }
.article-body :global(blockquote) {
border-left: 4px solid var(--color-primary);
padding-left: 24px;
margin: 32px 0;
font-style: italic;
color: var(--color-gray-600);
color: var(--color-gray-700);
}
.article-body :global(img) {
border-radius: 12px;
border-radius: var(--radius-md);
margin: 24px 0;
}
@@ -182,32 +166,30 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
flex-direction: column;
gap: 24px;
}
.sidebar-card {
background: var(--color-gray-100);
border-radius: 16px;
background: var(--color-bg-alt);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-xl);
padding: 28px;
}
.sidebar-title {
font-size: 18px;
font-weight: 700;
color: var(--color-dark);
margin-bottom: 16px;
font-family: var(--font-display);
font-size: 16px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 12px;
}
.sidebar-text {
font-size: 14px;
color: var(--color-gray-600);
line-height: 1.6;
margin-bottom: 16px;
}
.btn-sm {
padding: 12px 20px;
font-size: 14px;
border-radius: 8px;
font-weight: 600;
padding: 10px 20px;
font-size: 13px;
border-radius: var(--radius-md);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
display: inline-flex;
@@ -215,91 +197,39 @@ const formattedDate = post.data.date.toLocaleDateString('th-TH', {
justify-content: center;
}
.btn-dark {
background: var(--color-dark);
color: var(--color-white);
}
.btn-dark:hover {
background: var(--color-dark-light);
}
.btn-primary {
background: var(--color-primary);
color: var(--color-black);
}
.btn-primary:hover {
background: var(--color-primary-dark);
}
.btn-outline {
background: transparent;
border: 2px solid var(--color-dark);
color: var(--color-dark);
}
.btn-outline:hover {
background: var(--color-dark);
color: var(--color-white);
}
/* Related Posts */
.related-list {
display: flex;
flex-direction: column;
gap: 16px;
gap: 12px;
}
.related-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
padding: 8px;
background: var(--color-white);
border-radius: 12px;
transition: all 0.3s ease;
border-radius: var(--radius-md);
transition: all 0.2s ease;
}
.related-item:hover {
transform: translateX(4px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.related-item:hover { transform: translateX(4px); }
.related-item img {
width: 60px;
height: 60px;
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 8px;
border-radius: var(--radius-sm);
flex-shrink: 0;
}
.related-item span {
font-size: 14px;
font-weight: 600;
color: var(--color-dark);
font-size: 13px;
font-weight: 700;
color: var(--color-black);
line-height: 1.3;
}
@media (max-width: 1024px) {
.article-grid {
grid-template-columns: 1fr;
}
.article-sidebar {
order: -1;
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.article-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
.article-sidebar {
grid-template-columns: 1fr;
}
.article-body {
font-size: 16px;
}
.article-body { font-size: 16px; }
}
</style>
</style>