Add slim menu

This commit is contained in:
PascalMarchesseault
2024-09-11 15:41:44 -04:00
parent df223d219f
commit 13049e9d2a
3 changed files with 305 additions and 15 deletions

View File

@@ -0,0 +1,174 @@
<template>
<v-btn :style="{
backgroundColor: colorBorder, color: 'white',
borderRadius: '8px', padding:'0px 24px',
display: 'flex', alignItems: 'center',
justifyContent: 'center' }" @click="openDonationDialog()">
<div class="font-bold"> Je soutiens </div>
</v-btn>
<v-dialog v-model="donationModal" max-width="500">
<v-form>
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${colorBorder}` }">
<div class="py-4 text-2xl font-bold border-b mb-2">
Je Soutiens!
</div>
<div class="flex flex-row align-center px-3">
<img
:src="creatorLogo"
alt="Profile Image"
class="rounded-full"
width="40"
height="40"
:style="{ border: `2px solid ${colorAccent}` }">
<div class="capitalize px-2 text-2xl">{{ creatorName }}</div>
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
<v-icon>mdi-close</v-icon>
</v-btn>
</div>
<v-card-text>
<v-text-field
v-model="tipAmount"
type="number"
:min="0"
class="p-2"
label="Montant"
density="comfortable"
variant="outlined"
hide-details
clearable
inputmode="numeric"
@keydown="preventNonNumeric"
prepend-inner-icon="mdi-currency-usd"
></v-text-field>
<v-textarea v-model="tipMessage"
label="Message (facultatif)"
class="p-2"
density="comfortable"
variant="outlined"
hide-details
clearable
></v-textarea>
<v-btn variant="outlined" :style="{ borderColor: colorBorder, color: colorBorder }"
@click="goPay()" class="w-full mt-5">
Envoyez
</v-btn>
</v-card-text>
</v-card>
</v-form>
</v-dialog>
<v-dialog v-model="isPaymentDialogActive" max-width="720" persistent>
<template v-slot:default>
<v-card>
<div id="checkout">
</div>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn block class="ma-auto" style="width: 200px;" text @click="closeDialog()">Annuler</v-btn>
</v-card-actions>
</v-card>
</template>
</v-dialog>
</template>
<script setup>
import {useClient} from '@/plugins/api.js';
import {loadStripe} from '@stripe/stripe-js';
import {computed, onMounted, ref} from 'vue';
const props = defineProps({
colorBorder: {required: true},
colorAccent: {required: true},
creatorId: {type: String, required: true},
creatorName: {type: String, required: true},
creatorLogo: {required: true},
iconColorClass: {default: 'text-black'}
});
const colorBorder = computed(() => props.colorBorder)
const colorAccent = computed(() => props.colorAccent)
const creatorId = computed(() => props.creatorId)
const creatorName = computed(() => props.creatorName)
const creatorLogo = computed(() => props.creatorLogo)
const donationModal = ref(false);
function openDonationDialog() {
donationModal.value = true
}
function closeDonationDialog() {
donationModal.value = false
}
const isPaymentDialogActive = ref(false);
const tipAmount = ref(0);
const tipMessage = ref("");
let stripe = null;
let checkout;
onMounted(async () => {
stripe = await loadStripe(import.meta.env.VITE_STRIPE_API_KEY);
});
const fetchClientSecret = async () => {
const clientSecret = await createCheckoutSession();
return clientSecret;
};
async function createCheckoutSession() {
const client = useClient()
let clientSecret = await client.post('/api/Stripe', {
amount: (tipAmount.value * 100),
tipMessage: tipMessage.value,
creatorId: props.creatorId
});
let secret = clientSecret["data"];
return secret;
}
function closeDialog() {
isPaymentDialogActive.value = false;
if (checkout) {
checkout.destroy();
}
}
async function goPay() {
isPaymentDialogActive.value = true;
checkout = await stripe.initEmbeddedCheckout({
fetchClientSecret,
});
await checkout.mount('#checkout');
}
function preventNonNumeric(event) {
const key = event.key;
const allowedKeys = ['Backspace', 'ArrowLeft', 'ArrowRight', 'Delete'];
if (!/^\d$/.test(key) && !allowedKeys.includes(key)) {
event.preventDefault();
}
}
</script>

View File

@@ -0,0 +1,96 @@
<script setup>
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
import {computed, ref} from "vue";
const props = defineProps({
creator: {type: Object, required: true},
colorBorder: {required: true},
});
const colorBorder = computed(() => props.colorBorder);
const subscriptionStore = useSubscriptionStore();
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(props.creator.id));
function subscribeToCreator() {
subscriptionStore.subscribeTo(props.creator.id);
}
const showUnsubscribeModal = ref(false);
function unsubscribeFromCreator() {
subscriptionStore.unsubscribeFrom(props.creator.id);
showUnsubscribeModal.value = false;
}
</script>
<template>
<template v-if="isSubscribe">
<v-btn
class="mr-4"
:style="{
backgroundColor: colorBorder,
color: 'white',
borderRadius: '8px',
padding: '0px 24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'background-color 0.3s ease'
}"
@click="subscribeToCreator"
>
<div class="font-bold">{{ $t('subscribebutton.subscribe') }}</div>
</v-btn>
</template>
<template v-else>
<v-btn
class="mr-4"
:style="{
backgroundColor: colorBorder,
color: 'white',
borderRadius: '8px',
padding: '0px 24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'background-color 0.3s ease'
}"
@click="showUnsubscribeModal = true"
>
<div class="font-bold">{{ $t('subscribebutton.unsubscribe') }}</div>
</v-btn>
</template>
<v-dialog v-model="showUnsubscribeModal" max-width="500">
<v-card class="text-center rounded-xl"
:style="{ border: `3px solid ${creator.colors.menu}` }">
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
<div class="flex-1 text-center">
Déabonnement
</div>
</div>
<v-card-title>Confirmation</v-card-title>
<v-card-text>Êtes-vous sûr de vouloir vous désabonner ?</v-card-text>
<v-card-actions class="justify-center px-4 pb-4">
<v-btn text class="flex-grow-1" variant="outlined"
:style="{ backgroundColor: 'rgba(255, 255, 255, 0.1)', color: 'rgba(0, 0, 0, 0.4)' }"
@click="unsubscribeFromCreator">Oui
</v-btn>
<v-btn class="flex-grow-1"
:style="{ borderColor: creator.colors.menu, color: creator.colors.menu }" variant="outlined"
@click="showUnsubscribeModal = false">
<div :style="{ color: creator.colors.menu }">Non</div>
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

View File

@@ -31,8 +31,15 @@
iconColorClass="text-white"> iconColorClass="text-white">
</donation-button-banner> </donation-button-banner>
<div class="flex flex-column"> <div class="flex flex-column">
<subscribe-button :creator="creator" :color-border="creator.colors.menu"></subscribe-button> <!-- Bouton abonnement affiché seulement si non abonné -->
<div class="font-bold text-white flex justify-end mr-5 py-1.5">{{ creator.subscriberCount }} {{ $t('banner.subscription') }}</div> <subscribe-button
:creator="creator"
:color-border="creator.colors.menu">
</subscribe-button>
<div class="font-bold text-white flex justify-end mr-5 py-1.5">
{{ creator.subscriberCount }} {{ $t('banner.subscription') }}
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -42,7 +49,7 @@
<!-- Conteneur sticky --> <!-- Conteneur sticky -->
<div v-show="isSticky" class=" sticky-header fixed top-14 left-0 right-0 w-full z-20" <div v-show="isSticky" class=" sticky-header fixed top-14 left-0 right-0 w-full z-20"
:style="{ backgroundColor: creator.colors.bannerBottom || '#A30E79', borderBottom: '5px inset' + (creator.colors.menu || '#000') }"> :style="{ backgroundColor: creator.colors.bannerBottom || '#A30E79', borderBottom: '5px inset' + (creator.colors.menu || '#000') }">
<div class="shadow-2xl flex flex-row items-center py-2"> <div class="shadow-3xl flex flex-row items-center py-2 px-2">
<div> <div>
<img <img
class="max-w-[40px] max-h-[40px] ml-5 rounded-full" class="max-w-[40px] max-h-[40px] ml-5 rounded-full"
@@ -51,35 +58,53 @@
:style="{ borderColor: creator.colors.accent || '#A30E79', height: '190px'}" :style="{ borderColor: creator.colors.accent || '#A30E79', height: '190px'}"
/> />
</div> </div>
<div class="ml-5 text-white"> <div class="ml-5 text-white">
<p class="capitalize text-2xl font-bold">{{ creator.name }}</p> <p class="capitalize text-2xl font-bold">{{ creator.name }}</p>
</div> </div>
<div class="ml-auto flex flex-row space-x-2.5"> <div class="ml-auto flex flex-row space-x-2.5 ">
<donation-button-banner
<donation-button-banner-slim
:color-border="creator.colors.menu" :color-border="creator.colors.menu"
:color-accent="creator.colors.accent" :color-accent="creator.colors.accent"
:creator-id="creator.id" :creator-id="creator.id"
:creator-name="creator.name" :creator-name="creator.name"
:creator-logo="creator.images.logo" :creator-logo="creator.images.logo"
iconColorClass="text-white"> >
</donation-button-banner> </donation-button-banner-slim>
<subscribe-button :creator="creator" :color-border="creator.colors.menu"></subscribe-button>
<!-- Afficher le bouton d'abonnement seulement si l'utilisateur n'est pas abonné -->
<subscribe-button-slim
v-if="!isSubscribed"
:creator="creator"
:color-border="creator.colors.menu">
</subscribe-button-slim>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { useSubscriptionStore } from "@/stores/subscriptionStore.js";
import SubscribeButton from "@/views/creators/SubscribeButton.vue"; import SubscribeButton from "@/views/creators/SubscribeButton.vue";
import DonationButtonBanner from "@/views/creators/DonationButtonBanner.vue"; import DonationButtonBanner from "@/views/creators/DonationButtonBanner.vue";
import CreatorAbout from "@/views/creators/CreatorAbout.vue"; import CreatorAbout from "@/views/creators/CreatorAbout.vue";
import SubscribeButtonSlim from "@/views/creators/SubscribeButtonSlim.vue";
import DonationButtonBannerSlim from "@/views/creators/DonationButtonBannerSlim.vue";
const props = defineProps({ const props = defineProps({
creator: { type: Object, required: true } creator: { type: Object, required: true }
}); });
const subscriptionStore = useSubscriptionStore();
// Calculer si l'utilisateur est abonné
const isSubscribed = computed(() => subscriptionStore.isSubscribeTo(props.creator.id));
const isSticky = ref(false); const isSticky = ref(false);
const mainContainer = ref(null); const mainContainer = ref(null);
@@ -97,8 +122,3 @@ onMounted(() => {
}); });
</script> </script>
<style scoped>
.sticky-header {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>