Many an update!
This commit is contained in:
parent
85195d6c7a
commit
d588c49946
35 changed files with 3528 additions and 1142 deletions
126
app/components/MemberStatusBanner.vue
Normal file
126
app/components/MemberStatusBanner.vue
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<template>
|
||||
<div v-if="shouldShowBanner" class="w-full">
|
||||
<div
|
||||
:class="[
|
||||
'backdrop-blur-sm border rounded-lg p-4 flex items-start gap-4',
|
||||
statusConfig.bgColor,
|
||||
statusConfig.borderColor,
|
||||
]"
|
||||
>
|
||||
<Icon
|
||||
:name="statusConfig.icon"
|
||||
:class="['w-5 h-5 flex-shrink-0 mt-0.5', statusConfig.textColor]"
|
||||
/>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 :class="['font-semibold mb-1', statusConfig.textColor]">
|
||||
{{ statusConfig.label }}
|
||||
</h3>
|
||||
<p :class="['text-sm', statusConfig.textColor, 'opacity-90']">
|
||||
{{ bannerMessage }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<!-- Payment button for pending payment status -->
|
||||
<UButton
|
||||
v-if="isPendingPayment && nextAction"
|
||||
:color="getButtonColor(nextAction.color)"
|
||||
size="sm"
|
||||
:loading="isProcessingPayment"
|
||||
@click="handleActionClick"
|
||||
class="whitespace-nowrap"
|
||||
>
|
||||
{{ isProcessingPayment ? "Processing..." : nextAction.label }}
|
||||
</UButton>
|
||||
|
||||
<!-- Link button for other actions -->
|
||||
<NuxtLink
|
||||
v-else-if="nextAction && nextAction.link"
|
||||
:to="nextAction.link"
|
||||
:class="[
|
||||
'px-4 py-2 rounded-lg font-medium text-sm whitespace-nowrap transition-all',
|
||||
getActionButtonClass(nextAction.color),
|
||||
]"
|
||||
>
|
||||
{{ nextAction.label }}
|
||||
</NuxtLink>
|
||||
|
||||
<button
|
||||
v-if="dismissible"
|
||||
@click="isDismissed = true"
|
||||
class="text-ghost-400 hover:text-ghost-200 transition-colors"
|
||||
:aria-label="`Dismiss ${statusConfig.label} banner`"
|
||||
>
|
||||
<Icon name="heroicons:x-mark" class="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
dismissible: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
isPendingPayment,
|
||||
isSuspended,
|
||||
isCancelled,
|
||||
statusConfig,
|
||||
getNextAction,
|
||||
getBannerMessage,
|
||||
} = useMemberStatus();
|
||||
const { completePayment, isProcessingPayment } = useMemberPayment();
|
||||
|
||||
const isDismissed = ref(false);
|
||||
|
||||
// Handle action button click
|
||||
const handleActionClick = async () => {
|
||||
if (isPendingPayment.value) {
|
||||
try {
|
||||
await completePayment();
|
||||
} catch (error) {
|
||||
console.error("Payment failed:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Map color names to UButton color props
|
||||
const getButtonColor = (color) => {
|
||||
const colorMap = {
|
||||
orange: "orange",
|
||||
blue: "blue",
|
||||
gray: "gray",
|
||||
};
|
||||
return colorMap[color] || "blue";
|
||||
};
|
||||
|
||||
// Only show banner if status is not active
|
||||
const shouldShowBanner = computed(() => {
|
||||
if (isDismissed.value) return false;
|
||||
return isPendingPayment.value || isSuspended.value || isCancelled.value;
|
||||
});
|
||||
|
||||
const bannerMessage = computed(() => getBannerMessage());
|
||||
const nextAction = computed(() => getNextAction());
|
||||
|
||||
// Button styling based on color
|
||||
const getActionButtonClass = (color) => {
|
||||
const baseClass = "hover:scale-105 active:scale-95";
|
||||
const colorClasses = {
|
||||
orange: "bg-orange-600 text-white hover:bg-orange-700",
|
||||
blue: "bg-blue-600 text-white hover:bg-blue-700",
|
||||
gray: "bg-ghost-700 text-ghost-100 hover:bg-ghost-600",
|
||||
};
|
||||
return `${baseClass} ${colorClasses[color] || colorClasses.blue}`;
|
||||
};
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue