Add light/dark mode support with CSS variables
This commit is contained in:
parent
970b185151
commit
fb02688166
25 changed files with 1293 additions and 1177 deletions
|
|
@ -18,7 +18,7 @@
|
|||
<div
|
||||
class="w-8 h-8 border-4 border-whisper-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"
|
||||
></div>
|
||||
<p class="text-stone-300">Loading your dashboard...</p>
|
||||
<p class="text-ghost-300">Loading your dashboard...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -36,10 +36,10 @@
|
|||
<template #header>
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="flex-1">
|
||||
<h1 class="text-2xl font-bold text-stone-100 ethereal-text">
|
||||
<h1 class="text-2xl font-bold text-ghost-100 ethereal-text">
|
||||
Welcome to Ghost Guild, {{ memberData?.name }}!
|
||||
</h1>
|
||||
<p class="text-stone-300 mt-2">
|
||||
<p class="text-ghost-300 mt-2">
|
||||
Your membership is active and you're part of our cooperative
|
||||
community.
|
||||
</p>
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
</div>
|
||||
<div v-else class="flex-shrink-0">
|
||||
<div
|
||||
class="w-16 h-16 bg-ghost-700 border border-ghost-600 flex items-center justify-center text-stone-200 font-bold text-xl"
|
||||
class="w-16 h-16 bg-ghost-700 border border-ghost-600 flex items-center justify-center text-ghost-200 font-bold text-xl"
|
||||
>
|
||||
{{ memberData?.name?.charAt(0)?.toUpperCase() }}
|
||||
</div>
|
||||
|
|
@ -63,13 +63,13 @@
|
|||
|
||||
<div class="flex flex-wrap gap-4 text-sm">
|
||||
<div class="bg-ghost-800 border border-ghost-600 px-4 py-2">
|
||||
<span class="text-stone-400">Circle:</span>
|
||||
<span class="text-ghost-400">Circle:</span>
|
||||
<span class="font-medium text-whisper-300 ml-1 capitalize">{{
|
||||
memberData?.circle
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="bg-ghost-800 border border-ghost-600 px-4 py-2">
|
||||
<span class="text-stone-400">Contribution:</span>
|
||||
<span class="text-ghost-400">Contribution:</span>
|
||||
<span class="font-medium text-whisper-300 ml-1"
|
||||
>${{ memberData?.contributionTier }} CAD/month</span
|
||||
>
|
||||
|
|
@ -86,28 +86,16 @@
|
|||
}"
|
||||
>
|
||||
<template #header>
|
||||
<h2 class="text-xl font-bold text-stone-100 ethereal-text">
|
||||
<h2 class="text-xl font-bold text-ghost-100 ethereal-text">
|
||||
Quick Links
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<UButton
|
||||
to="/member/my-updates"
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500 justify-start"
|
||||
block
|
||||
>
|
||||
<template #leading>
|
||||
<Icon name="heroicons:pencil-square" class="w-5 h-5" />
|
||||
</template>
|
||||
Post an Update
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
disabled
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-500 cursor-not-allowed justify-start"
|
||||
class="border-ghost-600 text-ghost-500 cursor-not-allowed justify-start"
|
||||
block
|
||||
title="Coming soon"
|
||||
>
|
||||
|
|
@ -120,7 +108,7 @@
|
|||
<UButton
|
||||
disabled
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-500 cursor-not-allowed justify-start"
|
||||
class="border-ghost-600 text-ghost-500 cursor-not-allowed justify-start"
|
||||
block
|
||||
title="Coming soon"
|
||||
>
|
||||
|
|
@ -133,7 +121,7 @@
|
|||
<UButton
|
||||
disabled
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-500 cursor-not-allowed justify-start"
|
||||
class="border-ghost-600 text-ghost-500 cursor-not-allowed justify-start"
|
||||
block
|
||||
title="Coming soon"
|
||||
>
|
||||
|
|
@ -146,7 +134,7 @@
|
|||
<UButton
|
||||
to="/member/profile"
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500 justify-start"
|
||||
class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500 justify-start"
|
||||
block
|
||||
>
|
||||
<template #leading>
|
||||
|
|
@ -179,10 +167,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<h3 class="text-lg font-semibold mb-2 text-stone-100">
|
||||
<h3 class="text-lg font-semibold mb-2 text-ghost-100">
|
||||
Upcoming Events
|
||||
</h3>
|
||||
<p class="text-stone-300 mb-4">
|
||||
<p class="text-ghost-300 mb-4">
|
||||
Discover and register for community events and workshops.
|
||||
</p>
|
||||
|
||||
|
|
@ -191,7 +179,7 @@
|
|||
to="/events"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
>
|
||||
View Events
|
||||
</UButton>
|
||||
|
|
@ -217,8 +205,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<h3 class="text-lg font-semibold mb-2 text-stone-100">Community</h3>
|
||||
<p class="text-stone-300 mb-4">
|
||||
<h3 class="text-lg font-semibold mb-2 text-ghost-100">Community</h3>
|
||||
<p class="text-ghost-300 mb-4">
|
||||
Connect with other members in your circle and beyond.
|
||||
</p>
|
||||
|
||||
|
|
@ -227,7 +215,7 @@
|
|||
to="/members"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
>
|
||||
Browse Members
|
||||
</UButton>
|
||||
|
|
@ -253,10 +241,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<h3 class="text-lg font-semibold mb-2 text-stone-100">
|
||||
<h3 class="text-lg font-semibold mb-2 text-ghost-100">
|
||||
Account Settings
|
||||
</h3>
|
||||
<p class="text-stone-300 mb-4">
|
||||
<p class="text-ghost-300 mb-4">
|
||||
Manage your profile and membership settings.
|
||||
</p>
|
||||
|
||||
|
|
@ -265,7 +253,7 @@
|
|||
to="/member/profile#account"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
>
|
||||
Manage Account
|
||||
</UButton>
|
||||
|
|
@ -283,14 +271,14 @@
|
|||
>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-xl font-bold text-stone-100 ethereal-text">
|
||||
<h2 class="text-xl font-bold text-ghost-100 ethereal-text">
|
||||
Your Upcoming Events
|
||||
</h2>
|
||||
<UButton
|
||||
to="/events"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="text-stone-300 hover:text-stone-100"
|
||||
class="text-ghost-300 hover:text-ghost-100"
|
||||
>
|
||||
Browse All Events
|
||||
</UButton>
|
||||
|
|
@ -334,10 +322,10 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="font-semibold text-stone-100 mb-1">
|
||||
<h3 class="font-semibold text-ghost-100 mb-1">
|
||||
{{ evt.title }}
|
||||
</h3>
|
||||
<div class="flex items-center gap-4 text-sm text-stone-400">
|
||||
<div class="flex items-center gap-4 text-sm text-ghost-400">
|
||||
<span class="flex items-center gap-1">
|
||||
<Icon name="heroicons:calendar" class="w-4 h-4" />
|
||||
{{ formatEventDate(evt.startDate) }}
|
||||
|
|
@ -351,7 +339,7 @@
|
|||
<div class="flex-shrink-0">
|
||||
<Icon
|
||||
name="heroicons:chevron-right"
|
||||
class="w-5 h-5 text-stone-500"
|
||||
class="w-5 h-5 text-ghost-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -361,108 +349,20 @@
|
|||
<div v-else class="text-center py-8">
|
||||
<Icon
|
||||
name="heroicons:calendar-days"
|
||||
class="w-12 h-12 text-stone-600 mx-auto mb-3"
|
||||
class="w-12 h-12 text-ghost-600 mx-auto mb-3"
|
||||
/>
|
||||
<p class="text-stone-400 mb-4">
|
||||
<p class="text-ghost-400 mb-4">
|
||||
You haven't registered for any upcoming events
|
||||
</p>
|
||||
<UButton
|
||||
to="/events"
|
||||
size="sm"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
>
|
||||
Browse Events
|
||||
</UButton>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<!-- Community Pulse - Recent Updates -->
|
||||
<UCard
|
||||
class="sparkle-field"
|
||||
:ui="{
|
||||
root: 'bg-ghost-900 border border-ghost-700',
|
||||
header: 'border-b border-ghost-700 bg-ghost-900',
|
||||
body: 'bg-ghost-900',
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-xl font-bold text-stone-100 ethereal-text">
|
||||
Community Pulse
|
||||
</h2>
|
||||
<UButton
|
||||
to="/updates"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="text-stone-300 hover:text-stone-100"
|
||||
>
|
||||
View All
|
||||
</UButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="loadingUpdates" class="text-center py-8">
|
||||
<div
|
||||
class="w-6 h-6 border-2 border-whisper-500 border-t-transparent rounded-full animate-spin mx-auto"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="recentUpdates.length" class="space-y-4">
|
||||
<div
|
||||
v-for="update in recentUpdates"
|
||||
:key="update._id"
|
||||
class="border-l-2 border-ghost-600 pl-4 py-2"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<img
|
||||
v-if="
|
||||
update.author?.avatar && isValidAvatar(update.author.avatar)
|
||||
"
|
||||
:src="`/ghosties/Ghost-${capitalize(update.author.avatar)}.png`"
|
||||
:alt="update.author.name"
|
||||
class="w-8 h-8 flex-shrink-0"
|
||||
/>
|
||||
<div
|
||||
v-else-if="update.author?.name"
|
||||
class="w-8 h-8 bg-ghost-700 border border-ghost-600 flex items-center justify-center text-stone-200 text-xs font-bold flex-shrink-0"
|
||||
>
|
||||
{{ update.author.name.charAt(0).toUpperCase() }}
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-baseline gap-2 mb-1">
|
||||
<span class="font-semibold text-stone-100 text-sm">
|
||||
{{ update.author?.name }}
|
||||
</span>
|
||||
<span class="text-xs text-stone-500">
|
||||
{{ formatTimeAgo(update.createdAt) }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-stone-300 text-sm line-clamp-2">
|
||||
{{ update.content }}
|
||||
</p>
|
||||
<NuxtLink
|
||||
:to="`/updates/${update._id}`"
|
||||
class="text-xs text-whisper-400 hover:text-whisper-300 mt-1 inline-block"
|
||||
>
|
||||
Read more
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-center py-8">
|
||||
<p class="text-stone-400 mb-4">No community updates yet</p>
|
||||
<UButton
|
||||
to="/updates/new"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
class="border-ghost-600 text-stone-200 hover:bg-ghost-800 hover:border-whisper-500"
|
||||
>
|
||||
Post the First Update
|
||||
</UButton>
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
</UContainer>
|
||||
</div>
|
||||
|
|
@ -471,8 +371,6 @@
|
|||
<script setup>
|
||||
const { memberData, checkMemberStatus } = useAuth();
|
||||
|
||||
const recentUpdates = ref([]);
|
||||
const loadingUpdates = ref(false);
|
||||
const registeredEvents = ref([]);
|
||||
const loadingEvents = ref(false);
|
||||
|
||||
|
|
@ -506,21 +404,6 @@ const { pending: authPending } = await useLazyAsyncData(
|
|||
},
|
||||
);
|
||||
|
||||
// Load recent updates
|
||||
const loadRecentUpdates = async () => {
|
||||
loadingUpdates.value = true;
|
||||
try {
|
||||
const response = await $fetch("/api/updates", {
|
||||
params: { limit: 5, skip: 0 },
|
||||
});
|
||||
recentUpdates.value = response.updates;
|
||||
} catch (error) {
|
||||
console.error("Failed to load recent updates:", error);
|
||||
} finally {
|
||||
loadingUpdates.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Load registered events
|
||||
const loadRegisteredEvents = async () => {
|
||||
console.log(
|
||||
|
|
@ -575,23 +458,6 @@ const capitalize = (str) => {
|
|||
.join("-");
|
||||
};
|
||||
|
||||
const formatTimeAgo = (date) => {
|
||||
const now = new Date();
|
||||
const updateDate = new Date(date);
|
||||
const diffInSeconds = Math.floor((now - updateDate) / 1000);
|
||||
|
||||
if (diffInSeconds < 60) return "just now";
|
||||
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
||||
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
||||
if (diffInSeconds < 604800)
|
||||
return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
||||
|
||||
return updateDate.toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
};
|
||||
|
||||
// Helper functions for event display
|
||||
const getEventImageUrl = (featureImage) => {
|
||||
if (!featureImage) return "";
|
||||
|
|
@ -626,7 +492,6 @@ const formatEventTime = (dateString) => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadRecentUpdates();
|
||||
loadRegisteredEvents();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue