164 lines
8.8 KiB
Vue
164 lines
8.8 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import Auth from './Auth.vue'
|
|
import Profile from './Profile.vue'
|
|
import Strategies from './Strategies.vue'
|
|
import Competitors from './Competitors.vue'
|
|
import HotTweets from './HotTweets.vue'
|
|
|
|
const token = ref('')
|
|
const isLoading = ref(true)
|
|
const activeTab = ref('profile')
|
|
|
|
onMounted(() => {
|
|
chrome.storage.local.get(['jwt_token'], (res) => {
|
|
if (res.jwt_token) {
|
|
token.value = String(res.jwt_token)
|
|
}
|
|
isLoading.value = false
|
|
})
|
|
})
|
|
|
|
const onAuthenticated = (newToken: string) => {
|
|
token.value = newToken
|
|
}
|
|
|
|
const logout = () => {
|
|
chrome.storage.local.remove(['jwt_token', 'user_id'], () => {
|
|
token.value = ''
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-screen bg-[#09090b] text-[#f8fafc] font-sans selection:bg-rose-500/30 overflow-x-hidden">
|
|
|
|
<!-- Background Decor -->
|
|
<div class="fixed top-0 left-0 w-full h-full pointer-events-none overflow-hidden -z-10">
|
|
<div class="absolute -top-[10%] -left-[10%] w-[40%] h-[40%] bg-rose-900/10 blur-[120px] rounded-full"></div>
|
|
<div class="absolute top-[40%] -right-[5%] w-[30%] h-[50%] bg-blue-900/10 blur-[120px] rounded-full"></div>
|
|
</div>
|
|
|
|
<div class="max-w-[1200px] mx-auto px-8 py-12">
|
|
|
|
<!-- Premium Header -->
|
|
<header class="mb-16 flex justify-between items-center animate-in fade-in slide-in-from-top-4 duration-700">
|
|
<div class="space-y-2">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2.5 rounded-xl bg-gradient-to-br from-rose-500 to-rose-600 shadow-lg shadow-rose-900/20">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="text-white"><path d="m12 14 4-4"/><path d="M3.34 19a10 10 0 1 1 17.32 0"/></svg>
|
|
</div>
|
|
<h1 class="text-4xl font-black tracking-tight bg-gradient-to-br from-white via-white to-zinc-500 bg-clip-text text-transparent">
|
|
InsightReply <span class="text-rose-500">Dashboard</span>
|
|
</h1>
|
|
</div>
|
|
<p class="text-zinc-500 font-medium ml-1 flex items-center gap-2">
|
|
Professional Social Copilot
|
|
<span class="h-1 w-1 rounded-full bg-zinc-700"></span>
|
|
<span class="text-zinc-600 text-xs tracking-widest uppercase font-bold">Pro Max Edition</span>
|
|
</p>
|
|
</div>
|
|
|
|
<div v-if="token" class="flex items-center gap-6 bg-white/[0.03] border border-white/5 px-6 py-3 rounded-2xl backdrop-blur-xl">
|
|
<div class="flex items-center gap-2.5 px-3 py-1.5 rounded-full bg-emerald-500/10 border border-emerald-500/20">
|
|
<div class="w-2 h-2 rounded-full bg-emerald-500 shadow-[0_0_8px_#10b981]"></div>
|
|
<span class="text-xs font-bold text-emerald-400 uppercase tracking-widest">Active System</span>
|
|
</div>
|
|
<button @click="logout" class="text-sm font-bold text-zinc-500 hover:text-rose-400 transition-apple decoration-rose-500/30 underline-offset-4 hover:underline">Disconnect</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div v-if="isLoading" class="flex justify-center py-32">
|
|
<div class="w-10 h-10 border-2 border-white/10 border-t-rose-500 rounded-full animate-spin"></div>
|
|
</div>
|
|
|
|
<!-- Auth State -->
|
|
<div v-else-if="!token" class="flex justify-center py-10 animate-in fade-in zoom-in-95 duration-500">
|
|
<div class="w-full max-w-md bg-white/[0.02] border border-white/5 backdrop-blur-3xl rounded-[32px] p-10 shadow-2xl space-y-8">
|
|
<div class="text-center space-y-2">
|
|
<h2 class="text-2xl font-bold">Welcome Back</h2>
|
|
<p class="text-zinc-500 font-medium">Connect your account to synchronize your AI personality and custom strategies.</p>
|
|
</div>
|
|
<Auth @authenticated="onAuthenticated" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Dashboard Grid -->
|
|
<div v-else class="grid grid-cols-[280px_1fr] gap-12 items-start">
|
|
|
|
<!-- macOS Style Sidebar -->
|
|
<nav class="flex flex-col gap-1 animate-in fade-in slide-in-from-left-4 duration-700">
|
|
<div class="px-3 mb-4">
|
|
<h3 class="text-[10px] font-bold text-zinc-600 uppercase tracking-[0.2em]">Personalization</h3>
|
|
</div>
|
|
|
|
<button @click="activeTab = 'profile'"
|
|
:class="['flex items-center gap-4 px-4 py-3.5 rounded-2xl text-[13px] font-bold transition-apple tracking-tight active:scale-95',
|
|
activeTab === 'profile'
|
|
? 'bg-rose-500/10 text-rose-500 border border-rose-500/20 shadow-[0_4px_12px_rgba(244,63,94,0.1)]'
|
|
: 'text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.03] border border-transparent']">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" :class="['transition-apple', activeTab === 'profile' ? 'text-rose-500' : '']"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
Product Profile
|
|
</button>
|
|
|
|
<button @click="activeTab = 'strategies'"
|
|
:class="['flex items-center gap-4 px-4 py-3.5 rounded-2xl text-[13px] font-bold transition-apple tracking-tight active:scale-95',
|
|
activeTab === 'strategies'
|
|
? 'bg-rose-500/10 text-rose-500 border border-rose-500/20 shadow-[0_4px_12px_rgba(244,63,94,0.1)]'
|
|
: 'text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.03] border border-transparent']">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" :class="['transition-apple', activeTab === 'strategies' ? 'text-rose-500' : '']"><path d="m16 4 4 4-4 4"/><path d="M20 8H4v12"/></svg>
|
|
AI Strategies
|
|
</button>
|
|
|
|
<div class="px-3 mt-8 mb-4">
|
|
<h3 class="text-[10px] font-bold text-zinc-600 uppercase tracking-[0.2em]">Market Intelligence</h3>
|
|
</div>
|
|
|
|
<button @click="activeTab = 'competitors'"
|
|
:class="['flex items-center gap-4 px-4 py-3.5 rounded-2xl text-[13px] font-bold transition-apple tracking-tight active:scale-95',
|
|
activeTab === 'competitors'
|
|
? 'bg-rose-500/10 text-rose-500 border border-rose-500/20 shadow-[0_4px_12px_rgba(244,63,94,0.1)]'
|
|
: 'text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.03] border border-transparent']">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" :class="['transition-apple', activeTab === 'competitors' ? 'text-rose-500' : '']"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="M2 12h2"/><path d="M20 12h2"/></svg>
|
|
Competitor Radar
|
|
</button>
|
|
|
|
<button @click="activeTab = 'hottweets'"
|
|
:class="['flex items-center gap-4 px-4 py-3.5 rounded-2xl text-[13px] font-bold transition-apple tracking-tight active:scale-95',
|
|
activeTab === 'hottweets'
|
|
? 'bg-orange-500/10 text-orange-500 border border-orange-500/20 shadow-[0_4px_12px_rgba(249,115,22,0.1)]'
|
|
: 'text-zinc-500 hover:text-zinc-200 hover:bg-white/[0.03] border border-transparent']">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" :class="['transition-apple', activeTab === 'hottweets' ? 'text-orange-500' : '']"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5Z"/></svg>
|
|
Growth Opportunities
|
|
</button>
|
|
</nav>
|
|
|
|
<!-- Dynamic Content Window -->
|
|
<main class="bg-white/[0.02] border border-white/5 rounded-[40px] p-12 shadow-2xl backdrop-blur-3xl animate-in fade-in slide-in-from-right-8 duration-1000 min-h-[600px] hover:border-white/10 transition-apple">
|
|
<div v-show="activeTab === 'profile'" class="animate-in fade-in duration-500">
|
|
<Profile :token="token" />
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'strategies'" class="animate-in fade-in duration-500">
|
|
<Strategies :token="token" />
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'competitors'" class="animate-in fade-in duration-500">
|
|
<Competitors :token="token" />
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'hottweets'" class="animate-in fade-in duration-500 h-full">
|
|
<HotTweets :token="token" />
|
|
</div>
|
|
</main>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* No scoped styles needed as we use utility classes for maximum performance and build stability */
|
|
</style>
|