first commit
This commit is contained in:
419
frontend/src/views/HomePage.vue
Normal file
419
frontend/src/views/HomePage.vue
Normal file
@@ -0,0 +1,419 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user