Adds subscriptions
This commit is contained in:
13
src/main.js
13
src/main.js
@@ -9,17 +9,26 @@ import {createVuetify} from 'vuetify'
|
||||
import * as components from 'vuetify/components'
|
||||
import * as directives from 'vuetify/directives'
|
||||
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({
|
||||
components,
|
||||
directives
|
||||
});
|
||||
|
||||
createApp(App)
|
||||
const app = createApp(App)
|
||||
.use(createPinia())
|
||||
.use(vuetify)
|
||||
.use(router)
|
||||
.use(vueGoogleOauth, {
|
||||
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');
|
||||
|
||||
@@ -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 }
|
||||
})
|
||||
71
src/stores/subscriptionStore.js
Normal file
71
src/stores/subscriptionStore.js
Normal 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}
|
||||
});
|
||||
@@ -14,7 +14,8 @@
|
||||
:src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'"
|
||||
alt="Profile Image"
|
||||
class="ml-2 rounded-full"
|
||||
style="width: 48px; height: 48px;">
|
||||
width="48"
|
||||
height="48">
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -40,7 +41,8 @@
|
||||
:src="'/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'"
|
||||
alt="Profile Image"
|
||||
class="ml-2 rounded-full"
|
||||
style="width: 48px; height: 48px;">
|
||||
width="48"
|
||||
height="48">
|
||||
</span>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ let last_id = null
|
||||
|
||||
async function load({done}) {
|
||||
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}`
|
||||
|
||||
const response = await client.get(uri)
|
||||
|
||||
@@ -66,11 +66,8 @@
|
||||
<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-">
|
||||
<AboutYou :creator="creator"></AboutYou>
|
||||
<button class="text-white py-2 px-4 rounded"
|
||||
style="background-color: #333; transition: background-color 0.3s ease;"
|
||||
onmouseover="this.style.backgroundColor='#555';" onmouseout="this.style.backgroundColor='#333';">
|
||||
S'ABONNER
|
||||
</button>
|
||||
|
||||
<subscribe-button :creator="creator"></subscribe-button>
|
||||
|
||||
<CreatePostButton :creator="creator"/>
|
||||
|
||||
@@ -85,12 +82,12 @@
|
||||
import CreatePostButton from "@/views/contents/CreatePostButton.vue";
|
||||
import SizeIndicator from "@/views/tools/SizeIndicator.vue";
|
||||
import AboutYou from "@/views/creators/CreatorDescriptionBtn.vue";
|
||||
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
||||
|
||||
const props = defineProps({
|
||||
creator: {type: Object, required: true},
|
||||
});
|
||||
|
||||
|
||||
function GetActiveSocialNetworkUrls() {
|
||||
|
||||
const socialNetworks = [];
|
||||
|
||||
49
src/views/creators/SubscribeButton.vue
Normal file
49
src/views/creators/SubscribeButton.vue
Normal 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>
|
||||
35
src/views/creators/SubscriptionList.vue
Normal file
35
src/views/creators/SubscriptionList.vue
Normal 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>
|
||||
@@ -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">
|
||||
|
||||
<nav class="h-full grid grid-rows-[60px_1fr_auto]">
|
||||
<div></div>
|
||||
|
||||
<div class="pt-4 px-4">
|
||||
<h2>Subscriptions</h2>
|
||||
|
||||
<ul class="space-y">
|
||||
<li>
|
||||
<RouterLink to="/@leffet">
|
||||
<div class="nav-button">
|
||||
<v-icon class="mx-2">mdi-account</v-icon>
|
||||
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>
|
||||
<h2>Abonnements</h2>
|
||||
|
||||
<subscription-list>
|
||||
<template v-slot:default>
|
||||
<span>Aucun abonnement</span>
|
||||
</template>
|
||||
</subscription-list>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="border-t w-full py-10">
|
||||
@@ -54,13 +28,6 @@
|
||||
</template>
|
||||
|
||||
<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 {
|
||||
@apply font-sans font-bold ml-2;
|
||||
@@ -74,8 +41,5 @@ aside {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #903175 #f1f1f1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SiteMenu from "@/views/main/SiteMenu.vue";
|
||||
</script>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user