420 lines
13 KiB
Vue
420 lines
13 KiB
Vue
<script setup>
|
|
import { ref, onMounted } from "vue";
|
|
import { useRouter } from "vue-router";
|
|
import { useMarketStore } from "@/stores/market";
|
|
import { useAuthStore } from "@/stores/auth";
|
|
import {
|
|
TrendingUp,
|
|
Shield,
|
|
Zap,
|
|
Users,
|
|
ArrowRight,
|
|
Sparkles,
|
|
ChevronRight,
|
|
} from "lucide-vue-next";
|
|
|
|
const router = useRouter();
|
|
const marketStore = useMarketStore();
|
|
const authStore = useAuthStore();
|
|
|
|
const featuredItems = ref([]);
|
|
const recentSales = ref([]);
|
|
const isLoading = ref(true);
|
|
const stats = ref({
|
|
totalUsers: "50,000+",
|
|
totalTrades: "1M+",
|
|
avgTradeTime: "< 2 min",
|
|
activeListings: "25,000+",
|
|
});
|
|
|
|
const features = [
|
|
{
|
|
icon: Zap,
|
|
title: "Instant Trading",
|
|
description: "Lightning-fast transactions with automated trade bot system",
|
|
},
|
|
{
|
|
icon: Shield,
|
|
title: "Secure & Safe",
|
|
description: "Bank-grade security with SSL encryption and fraud protection",
|
|
},
|
|
{
|
|
icon: TrendingUp,
|
|
title: "Best Prices",
|
|
description: "Competitive marketplace pricing with real-time market data",
|
|
},
|
|
{
|
|
icon: Users,
|
|
title: "Active Community",
|
|
description: "Join thousands of traders in our vibrant marketplace",
|
|
},
|
|
];
|
|
|
|
onMounted(async () => {
|
|
isLoading.value = true;
|
|
await Promise.all([
|
|
marketStore.fetchFeaturedItems(),
|
|
marketStore.fetchRecentSales(6),
|
|
]);
|
|
featuredItems.value = marketStore.featuredItems.slice(0, 8);
|
|
recentSales.value = marketStore.recentSales;
|
|
isLoading.value = false;
|
|
});
|
|
|
|
const navigateToMarket = () => {
|
|
router.push("/market");
|
|
};
|
|
|
|
const navigateToSell = () => {
|
|
if (authStore.isAuthenticated) {
|
|
router.push("/sell");
|
|
} else {
|
|
authStore.login();
|
|
}
|
|
};
|
|
|
|
const formatPrice = (price) => {
|
|
return new Intl.NumberFormat("en-US", {
|
|
style: "currency",
|
|
currency: "USD",
|
|
}).format(price);
|
|
};
|
|
|
|
const formatTimeAgo = (timestamp) => {
|
|
const seconds = Math.floor((Date.now() - new Date(timestamp)) / 1000);
|
|
|
|
if (seconds < 60) return "Just now";
|
|
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
|
|
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
|
|
return `${Math.floor(seconds / 86400)}d ago`;
|
|
};
|
|
|
|
const getRarityColor = (rarity) => {
|
|
const colors = {
|
|
common: "text-gray-400",
|
|
uncommon: "text-green-400",
|
|
rare: "text-blue-400",
|
|
mythical: "text-purple-400",
|
|
legendary: "text-amber-400",
|
|
ancient: "text-red-400",
|
|
exceedingly: "text-orange-400",
|
|
};
|
|
return colors[rarity] || "text-gray-400";
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="home-page">
|
|
<!-- Hero Section -->
|
|
<section class="relative py-20 lg:py-32 overflow-hidden">
|
|
<!-- Background Effects -->
|
|
<div class="absolute inset-0 opacity-30">
|
|
<div
|
|
class="absolute top-1/4 left-1/4 w-96 h-96 bg-primary-500/20 rounded-full blur-3xl"
|
|
></div>
|
|
<div
|
|
class="absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent-blue/20 rounded-full blur-3xl"
|
|
></div>
|
|
</div>
|
|
|
|
<div class="container-custom relative z-10">
|
|
<div class="max-w-4xl mx-auto text-center">
|
|
<!-- Badge -->
|
|
<div
|
|
class="inline-flex items-center gap-2 px-4 py-2 bg-surface-light/50 backdrop-blur-sm border border-primary-500/30 rounded-full mb-6 animate-fade-in"
|
|
>
|
|
<Sparkles class="w-4 h-4 text-primary-500" />
|
|
<span class="text-sm font-medium text-gray-300"
|
|
>Premium CS2 & Rust Marketplace</span
|
|
>
|
|
</div>
|
|
|
|
<!-- Heading -->
|
|
<h1
|
|
class="text-4xl sm:text-5xl lg:text-7xl font-display font-bold mb-6 animate-slide-up"
|
|
>
|
|
<span class="text-white">Trade Your Skins</span>
|
|
<br />
|
|
<span class="gradient-text">Lightning Fast</span>
|
|
</h1>
|
|
|
|
<!-- Description -->
|
|
<p
|
|
class="text-lg sm:text-xl text-gray-400 mb-10 max-w-2xl mx-auto animate-slide-up"
|
|
style="animation-delay: 0.1s"
|
|
>
|
|
Buy, sell, and trade CS2 and Rust skins with instant delivery. Join
|
|
thousands of traders in the most trusted marketplace.
|
|
</p>
|
|
|
|
<!-- CTA Buttons -->
|
|
<div
|
|
class="flex flex-col sm:flex-row items-center justify-center gap-4 animate-slide-up"
|
|
style="animation-delay: 0.2s"
|
|
>
|
|
<button
|
|
@click="navigateToMarket"
|
|
class="btn btn-primary btn-lg group"
|
|
>
|
|
Browse Market
|
|
<ArrowRight
|
|
class="w-5 h-5 group-hover:translate-x-1 transition-transform"
|
|
/>
|
|
</button>
|
|
<button @click="navigateToSell" class="btn btn-outline btn-lg">
|
|
Start Selling
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Stats -->
|
|
<div
|
|
class="grid grid-cols-2 md:grid-cols-4 gap-6 mt-16 animate-slide-up"
|
|
style="animation-delay: 0.3s"
|
|
>
|
|
<div
|
|
v-for="(value, key) in stats"
|
|
:key="key"
|
|
class="p-6 bg-surface/50 backdrop-blur-sm rounded-xl border border-surface-lighter"
|
|
>
|
|
<div class="text-2xl sm:text-3xl font-bold text-primary-500 mb-1">
|
|
{{ value }}
|
|
</div>
|
|
<div class="text-sm text-gray-400 capitalize">
|
|
{{ key.replace(/([A-Z])/g, " $1").trim() }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Features Section -->
|
|
<section class="py-16 lg:py-24 bg-surface/30">
|
|
<div class="container-custom">
|
|
<div class="text-center mb-12">
|
|
<h2
|
|
class="text-3xl sm:text-4xl font-display font-bold text-white mb-4"
|
|
>
|
|
Why Choose TurboTrades?
|
|
</h2>
|
|
<p class="text-lg text-gray-400 max-w-2xl mx-auto">
|
|
Experience the best trading platform with industry-leading features
|
|
and security
|
|
</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
<div
|
|
v-for="feature in features"
|
|
:key="feature.title"
|
|
class="p-6 bg-surface rounded-xl border border-surface-lighter hover:border-primary-500/50 transition-all group"
|
|
>
|
|
<div
|
|
class="w-12 h-12 bg-primary-500/10 rounded-lg flex items-center justify-center mb-4 group-hover:bg-primary-500/20 transition-colors"
|
|
>
|
|
<component :is="feature.icon" class="w-6 h-6 text-primary-500" />
|
|
</div>
|
|
<h3 class="text-xl font-semibold text-white mb-2">
|
|
{{ feature.title }}
|
|
</h3>
|
|
<p class="text-gray-400 text-sm">{{ feature.description }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Featured Items Section -->
|
|
<section class="py-16 lg:py-24">
|
|
<div class="container-custom">
|
|
<div class="flex items-center justify-between mb-8">
|
|
<div>
|
|
<h2
|
|
class="text-3xl sm:text-4xl font-display font-bold text-white mb-2"
|
|
>
|
|
Featured Items
|
|
</h2>
|
|
<p class="text-gray-400">Hand-picked premium skins</p>
|
|
</div>
|
|
<button @click="navigateToMarket" class="btn btn-ghost group">
|
|
View All
|
|
<ChevronRight
|
|
class="w-4 h-4 group-hover:translate-x-1 transition-transform"
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Loading State -->
|
|
<div
|
|
v-if="isLoading"
|
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"
|
|
>
|
|
<div v-for="i in 8" :key="i" class="card">
|
|
<div class="aspect-square skeleton"></div>
|
|
<div class="card-body space-y-3">
|
|
<div class="h-4 skeleton w-3/4"></div>
|
|
<div class="h-3 skeleton w-1/2"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Items Grid -->
|
|
<div
|
|
v-else
|
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"
|
|
>
|
|
<div
|
|
v-for="item in featuredItems"
|
|
:key="item.id"
|
|
@click="router.push(`/item/${item.id}`)"
|
|
class="item-card group"
|
|
>
|
|
<!-- Image -->
|
|
<div class="relative">
|
|
<img :src="item.image" :alt="item.name" class="item-card-image" />
|
|
<div v-if="item.wear" class="item-card-wear">
|
|
{{ item.wear }}
|
|
</div>
|
|
<div
|
|
v-if="item.statTrak"
|
|
class="absolute top-2 right-2 badge badge-warning"
|
|
>
|
|
StatTrak™
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="p-4 space-y-3">
|
|
<div>
|
|
<h3 class="font-semibold text-white text-sm line-clamp-2 mb-1">
|
|
{{ item.name }}
|
|
</h3>
|
|
<p
|
|
:class="['text-xs font-medium', getRarityColor(item.rarity)]"
|
|
>
|
|
{{ item.rarity }}
|
|
</p>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-lg font-bold text-primary-500">
|
|
{{ formatPrice(item.price) }}
|
|
</span>
|
|
<button class="btn btn-sm btn-primary">Buy Now</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Recent Sales Section -->
|
|
<section class="py-16 lg:py-24 bg-surface/30">
|
|
<div class="container-custom">
|
|
<div class="text-center mb-12">
|
|
<h2
|
|
class="text-3xl sm:text-4xl font-display font-bold text-white mb-4"
|
|
>
|
|
Recent Sales
|
|
</h2>
|
|
<p class="text-lg text-gray-400">Live marketplace activity</p>
|
|
</div>
|
|
|
|
<div class="max-w-4xl mx-auto space-y-3">
|
|
<div
|
|
v-for="sale in recentSales"
|
|
:key="sale.id"
|
|
class="flex items-center gap-4 p-4 bg-surface rounded-lg border border-surface-lighter hover:border-primary-500/30 transition-colors"
|
|
>
|
|
<img
|
|
:src="sale.itemImage"
|
|
:alt="sale.itemName"
|
|
class="w-16 h-16 object-contain bg-surface-light rounded-lg"
|
|
/>
|
|
<div class="flex-1 min-w-0">
|
|
<h4 class="font-medium text-white text-sm truncate">
|
|
{{ sale.itemName }}
|
|
</h4>
|
|
<p class="text-xs text-gray-400">{{ sale.wear }}</p>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="font-bold text-accent-green">
|
|
{{ formatPrice(sale.price) }}
|
|
</div>
|
|
<div class="text-xs text-gray-500">
|
|
{{ formatTimeAgo(sale.soldAt) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- CTA Section -->
|
|
<section class="py-16 lg:py-24">
|
|
<div class="container-custom">
|
|
<div
|
|
class="relative overflow-hidden rounded-2xl bg-gradient-to-r from-primary-600 to-primary-800 p-12 text-center"
|
|
>
|
|
<!-- Background Pattern -->
|
|
<div class="absolute inset-0 opacity-10">
|
|
<div
|
|
class="absolute top-0 left-1/4 w-72 h-72 bg-white rounded-full blur-3xl"
|
|
></div>
|
|
<div
|
|
class="absolute bottom-0 right-1/4 w-72 h-72 bg-white rounded-full blur-3xl"
|
|
></div>
|
|
</div>
|
|
|
|
<div class="relative z-10 max-w-3xl mx-auto">
|
|
<h2
|
|
class="text-3xl sm:text-5xl font-display font-bold text-white mb-6"
|
|
>
|
|
Ready to Start Trading?
|
|
</h2>
|
|
<p class="text-lg text-primary-100 mb-8">
|
|
Join TurboTrades today and experience the fastest, most secure way
|
|
to trade gaming skins
|
|
</p>
|
|
<div
|
|
class="flex flex-col sm:flex-row items-center justify-center gap-4"
|
|
>
|
|
<button
|
|
v-if="!authStore.isAuthenticated"
|
|
@click="authStore.login"
|
|
class="btn btn-lg bg-white text-primary-600 hover:bg-gray-100"
|
|
>
|
|
<img
|
|
src="https://community.cloudflare.steamstatic.com/public/images/signinthroughsteam/sits_01.png"
|
|
alt="Sign in through Steam"
|
|
class="h-6"
|
|
/>
|
|
</button>
|
|
<button
|
|
v-else
|
|
@click="navigateToMarket"
|
|
class="btn btn-lg bg-white text-primary-600 hover:bg-gray-100"
|
|
>
|
|
Browse Market
|
|
<ArrowRight class="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.home-page {
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.line-clamp-2 {
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
</style>
|