feat(frontend): update pages, components and branding

Refresh Astro frontend implementation including new pages (Portfolio, Teams, Services), components, and styling updates.
This commit is contained in:
2026-02-11 11:50:42 +08:00
parent be7fc902fb
commit 9c2181f743
49 changed files with 9699 additions and 899 deletions

View File

@@ -0,0 +1,309 @@
---
/**
* BenefitsSection - Work benefits section for Teams page
* Pixel-perfect implementation based on Webflow design
* Features 6 benefit cards with alternating layout
*/
interface BenefitItem {
title: string
icon: string
}
interface Props {
benefits?: BenefitItem[]
}
const defaultBenefits: BenefitItem[] = [
{
title: '高績效、高獎金\n新人開張獎金',
icon: 'bonus',
},
{
title: '生日慶生、電影日\n員工下午茶',
icon: 'birthday',
},
{
title: '教育訓練補助',
icon: 'education',
},
{
title: '寬敞的工作空間',
icon: 'workspace',
},
{
title: '員工國內外旅遊\n部門聚餐、年終活動',
icon: 'travel',
},
{
title: '入職培訓及團隊建設',
icon: 'training',
},
]
const benefits = Astro.props.benefits || defaultBenefits
// Icon SVG components (placeholder for now, replace with actual SVG)
const getIconSVG = (iconType: string) => {
const icons: Record<string, string> = {
bonus: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">💰</text>
</svg>`,
birthday: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🎂</text>
</svg>`,
education: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">📚</text>
</svg>`,
workspace: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🏢</text>
</svg>`,
travel: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">✈️</text>
</svg>`,
training: `<svg viewBox="0 0 200 200" class="benefit-icon-svg">
<circle cx="100" cy="70" r="40" fill="#23608c" opacity="0.2"/>
<rect x="60" y="100" width="80" height="60" rx="8" fill="#23608c"/>
<text x="100" y="140" text-anchor="middle" fill="white" font-size="36">🤝</text>
</svg>`,
}
return icons[iconType] || icons.bonus
}
---
<section class="section-benefit" aria-labelledby="benefits-heading">
<div class="container w-container">
<!-- Section Header -->
<div class="section_header_w_line">
<div class="divider_line"></div>
<div class="header_subtitle">
<h2 id="benefits-heading" class="header_subtitle_head">工作福利</h2>
<p class="header_subtitle_paragraph">Benefit Package</p>
</div>
<div class="divider_line"></div>
</div>
<!-- Benefits Grid -->
<div class="benefit-grid-wrapper">
{
benefits.map((benefit, index) => (
<div class={`benefit-card ${index % 2 === 0 ? 'benefit-card' : 'benefit-card-opposite'}`}>
<!-- Odd: Icon on right, Even: Icon on left -->
{
index % 2 === 0 ? (
<>
<div class="benefit-content">
<h3 class="benefit-title-text">{benefit.title}</h3>
</div>
<div class="benefit-image-right" set:html={getIconSVG(benefit.icon)} />
</>
) : (
<>
<div class="benefit-image-left" set:html={getIconSVG(benefit.icon)} />
<div class="benefit-content">
<h3 class="benefit-title-text">{benefit.title}</h3>
</div>
</>
)
}
</div>
))
}
</div>
</div>
</section>
<style>
/* Benefits Section Styles - Pixel-perfect from Webflow */
.section-benefit {
padding: 60px 20px;
background-color: #ffffff;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.w-container {
max-width: 1200px;
margin: 0 auto;
}
/* Section Header */
.section_header_w_line {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
margin-bottom: 48px;
}
.header_subtitle {
text-align: center;
}
.header_subtitle_head {
color: var(--color-enchunblue);
font-family: "Noto Sans TC", sans-serif;
font-weight: 700;
font-size: 2rem;
margin-bottom: 8px;
}
.header_subtitle_paragraph {
color: var(--color-gray-600);
font-family: "Quicksand", sans-serif;
font-weight: 400;
font-size: 1rem;
}
.divider_line {
width: 40px;
height: 2px;
background-color: var(--color-enchunblue);
}
/* Benefits Grid */
.benefit-grid-wrapper {
max-width: 1000px;
margin: 0 auto;
}
/* Benefit Card */
.benefit-card,
.benefit-card-opposite {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
margin-bottom: 60px;
}
/* Odd cards: icon on right */
.benefit-card {
grid-template-areas: "content image";
}
.benefit-card .benefit-content {
grid-area: content;
text-align: left;
}
.benefit-card .benefit-image-right {
grid-area: image;
display: flex;
justify-content: center;
align-items: center;
}
/* Even cards: icon on left */
.benefit-card-opposite {
grid-template-areas: "image content";
}
.benefit-card-opposite .benefit-content {
grid-area: content;
text-align: left;
}
.benefit-card-opposite .benefit-image-left {
grid-area: image;
display: flex;
justify-content: center;
align-items: center;
}
/* Benefit Title */
.benefit-title-text {
font-size: 1.5rem;
font-weight: 600;
color: var(--color-tarawera, #23608c);
white-space: pre-line;
line-height: 1.4;
}
/* Benefit Icon */
.benefit-icon-svg {
width: 120px;
height: 120px;
}
.benefit-image-right,
.benefit-image-left {
display: flex;
justify-content: center;
align-items: center;
}
.benefit-image-right svg,
.benefit-image-left svg {
width: 120px;
height: 120px;
}
/* Responsive Adjustments */
@media (max-width: 991px) {
.benefit-card,
.benefit-card-opposite {
gap: 24px;
margin-bottom: 40px;
}
.benefit-title-text {
font-size: 1.25rem;
}
}
@media (max-width: 767px) {
.section-benefit {
padding: 40px 16px;
}
.section_header_w_line {
flex-wrap: wrap;
}
.benefit-card,
.benefit-card-opposite {
grid-template-columns: 1fr;
grid-template-areas: "image" "content" !important;
gap: 24px;
margin-bottom: 48px;
}
.benefit-content {
text-align: center !important;
}
.benefit-image-right,
.benefit-image-left {
order: -1;
}
.benefit-title-text {
font-size: 1.125rem;
}
.benefit-icon-svg {
width: 100px;
height: 100px;
}
.benefit-image-right svg,
.benefit-image-left svg {
width: 100px;
height: 100px;
}
}
</style>