Adds subscriptions

This commit is contained in:
Jonathan Bourdon
2024-08-04 03:02:50 -04:00
parent 78ead7e387
commit d23c565770
9 changed files with 190 additions and 75 deletions

View File

@@ -9,17 +9,26 @@ import {createVuetify} from 'vuetify'
import * as components from 'vuetify/components' import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives' import * as directives from 'vuetify/directives'
import vueGoogleOauth from 'vue3-google-login' import vueGoogleOauth from 'vue3-google-login'
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
import {useAuthStore} from "@/stores/authStore.js";
import {useUserStore} from "@/stores/userStore.js";
const vuetify = createVuetify({ const vuetify = createVuetify({
components, components,
directives directives
}); });
createApp(App) const app = createApp(App)
.use(createPinia()) .use(createPinia())
.use(vuetify) .use(vuetify)
.use(router) .use(router)
.use(vueGoogleOauth, { .use(vueGoogleOauth, {
clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID, clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID,
}) })
.mount('#app');
// this force the creation of the stores
const subscriptionStore = useSubscriptionStore()
const authStore = useAuthStore()
const userStore = useUserStore()
app.mount('#app');

View File

@@ -1,12 +0,0 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

View File

@@ -0,0 +1,71 @@
import {defineStore} from "pinia";
import {useSessionStorage} from "@vueuse/core";
import {useClient} from "@/plugins/api.js";
import {useAuthStore} from "@/stores/authStore.js";
import {watch} from "vue";
export const useSubscriptionStore = defineStore(
'subscription',
() => {
const subscriptions = useSessionStorage(
'subscription-subscriptions',
{})
const authStore = useAuthStore()
const authWatcher = watch(
() => authStore.isAuthenticated,
async (newValue) => {
if (newValue) {
await loadSubscriptions()
} else {
subscriptions.value = {}
}
})
function isSubscribeTo(creatorId) {
return !!subscriptions.value[creatorId];
}
async function subscribeTo(creatorId) {
try {
const client = useClient()
const response = await client.post(
`/api/creators/${creatorId}/subscribe`
);
subscriptions.value[creatorId] = response.data;
} catch (error) {
console.error("Error subscribing to creator", error);
}
}
async function unsubscribeFrom(creatorId) {
try {
const client = useClient()
const response = await client.post(
`/api/creators/${creatorId}/unsubscribe`
);
delete subscriptions.value[creatorId];
} catch (error) {
console.error("Error unsubscribing from creator", error);
}
}
async function loadSubscriptions() {
try {
const client = useClient()
const response = await client.get(`/api/subscriptions`);
subscriptions.value = response.data.reduce(
(acc, sub) => {
acc[sub.creatorId] = sub;
return acc;
},
{});
} catch (error) {
console.error("Error loading subscriptions:", error);
}
}
return {subscriptions, isSubscribeTo, subscribeTo, unsubscribeFrom}
});

View File

@@ -14,7 +14,8 @@
:src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'" :src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'"
alt="Profile Image" alt="Profile Image"
class="ml-2 rounded-full" class="ml-2 rounded-full"
style="width: 48px; height: 48px;"> width="48"
height="48">
</span> </span>
</button> </button>
@@ -40,7 +41,8 @@
:src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'" :src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'"
alt="Profile Image" alt="Profile Image"
class="ml-2 rounded-full" class="ml-2 rounded-full"
style="width: 48px; height: 48px;"> width="48"
height="48">
</span> </span>
</button> </button>

View File

@@ -45,7 +45,7 @@ let last_id = null
async function load({done}) { async function load({done}) {
try { try {
let uri = `/api/contents/user/${props.creatorId}?page_size=${page_size}` let uri = `/api/contents/creator/${props.creatorId}?page_size=${page_size}`
if (last_id !== null) uri = uri + `&last_id=${last_id}` if (last_id !== null) uri = uri + `&last_id=${last_id}`
const response = await client.get(uri) const response = await client.get(uri)

View File

@@ -66,11 +66,8 @@
<div <div
class="flex flex-wrap items-center justify-center mt-2 sm:mt-8 md:mt-4 lg:mt-0 lg:ml-auto space-x-2 sm:space-x-4 ml-"> class="flex flex-wrap items-center justify-center mt-2 sm:mt-8 md:mt-4 lg:mt-0 lg:ml-auto space-x-2 sm:space-x-4 ml-">
<AboutYou :creator="creator"></AboutYou> <AboutYou :creator="creator"></AboutYou>
<button class="text-white py-2 px-4 rounded"
style="background-color: #333; transition: background-color 0.3s ease;" <subscribe-button :creator="creator"></subscribe-button>
onmouseover="this.style.backgroundColor='#555';" onmouseout="this.style.backgroundColor='#333';">
S'ABONNER
</button>
<CreatePostButton :creator="creator"/> <CreatePostButton :creator="creator"/>
@@ -85,12 +82,12 @@
import CreatePostButton from "@/views/contents/CreatePostButton.vue"; import CreatePostButton from "@/views/contents/CreatePostButton.vue";
import SizeIndicator from "@/views/tools/SizeIndicator.vue"; import SizeIndicator from "@/views/tools/SizeIndicator.vue";
import AboutYou from "@/views/creators/CreatorDescriptionBtn.vue"; import AboutYou from "@/views/creators/CreatorDescriptionBtn.vue";
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
const props = defineProps({ const props = defineProps({
creator: {type: Object, required: true}, creator: {type: Object, required: true},
}); });
function GetActiveSocialNetworkUrls() { function GetActiveSocialNetworkUrls() {
const socialNetworks = []; const socialNetworks = [];

View File

@@ -0,0 +1,49 @@
<script setup>
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
import {computed} from "vue";
const props = defineProps({
creator: {type: Object, required: true},
});
const subscriptionStore = useSubscriptionStore()
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(props.creator.id))
function subscribeToCreator() {
subscriptionStore.subscribeTo(props.creator.id)
}
function unsubscribeFromCreator() {
subscriptionStore.unsubscribeFrom(props.creator.id)
}
</script>
<template>
<template v-if="isSubscribe">
<v-btn class="action"
@click="subscribeToCreator()"
style="transition: background-color 0.3s ease;">
S'ABONNER
</v-btn>
</template>
<template v-else>
<v-btn class="action"
@click="unsubscribeFromCreator()"
style="transition: background-color 0.3s ease;">
SE DESABONNER
</v-btn>
</template>
</template>
<style scoped>
.action {
@apply py-2 px-4 rounded bg-gray-100 hover:bg-gray-300
}
</style>

View File

@@ -0,0 +1,35 @@
<script setup>
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
const subscriptionStore = useSubscriptionStore()
</script>
<template>
<template v-if="Object.keys(subscriptionStore.subscriptions).length > 0">
<template v-for="subscription in subscriptionStore.subscriptions">
<RouterLink :to="`/@${subscription.creatorName}`">
<div class="flex items-center content-center font-sans font-semibold pt-2">
<img :src="subscription.creatorPortraitUrl"
alt="Profile Image"
class="rounded-full mx-2"
width="32px"
height="32px">
{{ subscription.creatorName }}
</div>
</RouterLink>
</template>
</template>
<template v-else>
<slot>
<span>Placeholder when there are no subscriptions</span>
</slot>
</template>
</template>

View File

@@ -1,49 +1,23 @@
<template> <script setup>
import SiteMenu from "@/views/main/SiteMenu.vue";
import SubscriptionList from "@/views/creators/SubscriptionList.vue";
</script>
<template>
<aside class="relative h-full overflow-y-auto custom-scrollbar"> <aside class="relative h-full overflow-y-auto custom-scrollbar">
<nav class="h-full grid grid-rows-[60px_1fr_auto]"> <nav class="h-full grid grid-rows-[60px_1fr_auto]">
<div></div> <div></div>
<div class="pt-4 px-4"> <div class="pt-4 px-4">
<h2>Subscriptions</h2> <h2>Abonnements</h2>
<ul class="space-y"> <subscription-list>
<li> <template v-slot:default>
<RouterLink to="/@leffet"> <span>Aucun abonnement</span>
<div class="nav-button"> </template>
<v-icon class="mx-2">mdi-account</v-icon> </subscription-list>
L'Effet
</div>
</RouterLink>
<RouterLink to="/@chloebeaugrand">
<div class="nav-button">
<v-icon class="mx-2">mdi-account</v-icon>
Chloe Beaugrand
</div>
</RouterLink>
<RouterLink to="/@guillaumeaime">
<div class="nav-button">
<v-icon class="mx-2">mdi-account</v-icon>
Guillaume Aime
</div>
</RouterLink>
<RouterLink to="/@mathieucaron">
<div class="nav-button">
<v-icon class="mx-2">mdi-account</v-icon>
Mathieu Caron
</div>
</RouterLink>
<RouterLink to="/@arps">
<div class="nav-button">
<v-icon class="mx-2">mdi-account</v-icon>
ARPS
</div>
</RouterLink>
</li>
</ul>
</div> </div>
<div class="border-t w-full py-10"> <div class="border-t w-full py-10">
@@ -54,13 +28,6 @@
</template> </template>
<style scoped> <style scoped>
.nav-button {
@apply rounded p-1 m-1 text-gray-800 font-sans;
}
.nav-button:hover {
@apply bg-[#903175] text-gray-200;
}
h2 { h2 {
@apply font-sans font-bold ml-2; @apply font-sans font-bold ml-2;
@@ -74,8 +41,5 @@ aside {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: #903175 #f1f1f1; scrollbar-color: #903175 #f1f1f1;
} }
</style>
<script setup lang="ts"> </style>
import SiteMenu from "@/views/main/SiteMenu.vue";
</script>