Files
website/website/resources/ts/Pages/Marketing/GameServers.vue
Claude Dev 169b06e349 Dynamic product pages + Battlefield ACP marketing page
- Web Hosting & Game Servers now pull plans from database (same pattern as VPS/Dedicated)
- Add 6 game server plans to PlanSeeder (Minecraft, Rust, ARK, Valheim, CS2, Palworld)
- Create Battlefield ACP marketing page with ProCon replacement hero, 6 feature cards,
  ML analytics, ban appeals, PunkBuster screenshots, Discord integration sections
- Add Battlefield ACP to Products dropdown navigation
- Marketing pages use SectionHeader component, fade-in animations, Vuexy design patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:32:35 -05:00

176 lines
6.6 KiB
Vue

<script lang="ts" setup>
import { usePage } from '@inertiajs/vue3'
import { computed } from 'vue'
import MarketingLayout from '@/Layouts/MarketingLayout.vue'
import SectionHeader from '@/Components/Marketing/SectionHeader.vue'
defineOptions({ layout: MarketingLayout })
interface Plan {
id: number
name: string
slug: string
description: string | null
price: string
features: Record<string, string | number> | null
}
interface PageProps {
plans: Plan[]
domains: { marketing: string; account: string; admin: string }
}
interface Feature {
icon: string
title: string
description: string
}
const gameIcons: Record<string, string> = {
'Minecraft': 'tabler-cube',
'Rust': 'tabler-shield',
'ARK: Survival Evolved': 'tabler-dinosaur',
'Valheim': 'tabler-sword',
'CS2': 'tabler-crosshair',
'Palworld': 'tabler-paw',
}
const page = usePage()
const props = computed(() => page.props as unknown as PageProps)
const plans = computed(() => props.value.plans || [])
function formatPrice(plan: Plan): string {
const price = parseFloat(plan.price) || 0
return price % 1 === 0 ? `$${price}` : `$${price.toFixed(2)}`
}
function getIcon(plan: Plan): string {
return gameIcons[plan.name] || 'tabler-device-gamepad-2'
}
function getFeature(plan: Plan, key: string): string {
return String(plan.features?.[key] ?? '-')
}
const features: Feature[] = [
{ icon: 'tabler-bolt', title: 'Low Latency', description: 'Optimized network routing for minimal ping.' },
{ icon: 'tabler-puzzle', title: 'Mod Support', description: 'Easy plugin and mod installation with one-click tools.' },
{ icon: 'tabler-shield-check', title: 'DDoS Protection', description: 'Always-on protection to keep your server online.' },
{ icon: 'tabler-clock', title: 'Instant Setup', description: 'Your game server is ready in under 5 minutes.' },
]
</script>
<template>
<div>
<!-- Hero -->
<div class="hero-section" style="padding-block: 5.25rem; background: linear-gradient(135deg, rgb(var(--v-theme-error), 0.1), rgb(var(--v-theme-surface)));">
<VContainer class="text-center">
<VChip color="error" variant="tonal" class="mb-4">Game Servers</VChip>
<h1 class="text-h2 font-weight-bold mb-3">
Game Server <span class="hero-gradient-text">Hosting</span>
</h1>
<p class="text-h6 text-medium-emphasis font-weight-regular mb-4 mx-auto" style="max-width: 600px;">
Low-latency game server hosting with instant setup, mod support, and DDoS protection.
</p>
<VChip color="warning" variant="flat" class="mb-8">
<VIcon icon="tabler-clock" start size="16" />
Coming Soon
</VChip>
<div>
<VBtn color="error" size="x-large" rounded="lg">
Notify Me
<VIcon icon="tabler-bell" end />
</VBtn>
</div>
</VContainer>
</div>
<!-- Supported Games -->
<VContainer class="marketing-section">
<SectionHeader
label="Games"
label-color="error"
title="Supported Games"
highlight-word="Games"
subtitle="Popular titles with more being added regularly."
/>
<VRow>
<VCol v-for="(plan, index) in plans" :key="plan.id" cols="12" sm="6" md="4">
<VCard variant="outlined" :class="['h-100 feature-card-hover', `fade-in-up stagger-delay-${index + 1}`]">
<VCardText class="pa-5">
<div class="d-flex align-center ga-4 mb-3">
<VAvatar color="error" variant="tonal" size="48">
<VIcon :icon="getIcon(plan)" size="24" />
</VAvatar>
<div>
<h3 class="text-subtitle-1 font-weight-bold">{{ plan.name }}</h3>
<p class="text-body-2 text-medium-emphasis mb-0">{{ plan.description }}</p>
</div>
</div>
<VDivider class="mb-3" />
<div class="d-flex flex-wrap ga-2 mb-3">
<VChip size="x-small" variant="tonal" color="error">{{ getFeature(plan, 'ram') }} RAM</VChip>
<VChip size="x-small" variant="tonal" color="error">{{ getFeature(plan, 'slots') }}</VChip>
<VChip size="x-small" variant="tonal" color="error">{{ getFeature(plan, 'storage') }}</VChip>
<VChip size="x-small" variant="tonal" color="error">{{ getFeature(plan, 'mods') }}</VChip>
</div>
<div class="d-flex align-center justify-space-between">
<span class="text-h6 text-error font-weight-bold">{{ formatPrice(plan) }}<span class="text-body-2 text-medium-emphasis font-weight-regular">/mo</span></span>
<VChip color="warning" size="x-small" variant="flat">Coming Soon</VChip>
</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</VContainer>
<!-- Features -->
<div class="section-alt-bg marketing-section">
<VContainer>
<SectionHeader
label="Features"
label-color="error"
title="Why Gamers Choose EZSCALE"
highlight-word="EZSCALE"
/>
<VRow>
<VCol v-for="(feature, index) in features" :key="feature.title" cols="12" sm="6" md="3">
<VCard variant="flat" :class="['text-center pa-4 h-100 bg-transparent feature-card-hover', `fade-in-up stagger-delay-${index + 1}`]">
<VAvatar color="error" variant="tonal" size="56" class="mb-3">
<VIcon :icon="feature.icon" size="28" />
</VAvatar>
<h3 class="text-subtitle-1 font-weight-bold mb-1">{{ feature.title }}</h3>
<p class="text-body-2 text-medium-emphasis mb-0">{{ feature.description }}</p>
</VCard>
</VCol>
</VRow>
</VContainer>
</div>
<!-- CTA -->
<div class="marketing-section" style="background: linear-gradient(135deg, rgb(var(--v-theme-error), 0.08), rgb(var(--v-theme-surface)));">
<VContainer class="text-center">
<h2 class="text-h4 font-weight-bold mb-3">Be the First to Know</h2>
<p class="text-body-1 text-medium-emphasis mb-6">
Game server hosting is coming soon. Sign up to get notified when we launch.
</p>
<div class="d-flex ga-3 justify-center flex-wrap">
<VBtn color="error" size="large" rounded="lg">
Notify Me
<VIcon icon="tabler-bell" end />
</VBtn>
<a href="/contact" class="text-decoration-none">
<VBtn color="error" variant="outlined" size="large" rounded="lg">
Contact Us
</VBtn>
</a>
</div>
</VContainer>
</div>
</div>
</template>