mirror of
https://github.com/versia-pub/frontend.git
synced 2026-03-13 11:39:16 +01:00
feat: ✨ Refactor notifications
This commit is contained in:
parent
d32f4d6899
commit
a6c5093cf5
12 changed files with 213 additions and 453 deletions
87
components/notifications/follow-request.vue
Normal file
87
components/notifications/follow-request.vue
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<div v-if="relationship?.requested_by !== false" class="flex flex-row items-center gap-3 p-4">
|
||||
<NuxtLink class="relative size-10">
|
||||
<Avatar class="size-10 rounded border border-border">
|
||||
<AvatarImage :src="follower.avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
</NuxtLink>
|
||||
<div class="flex flex-col gap-0.5 justify-center flex-1 text-left leading-tight text-sm">
|
||||
<span class="truncate font-semibold">{{
|
||||
follower.display_name
|
||||
}}</span>
|
||||
<span class="truncate tracking-tight">
|
||||
<CopyableText :text="follower.acct">
|
||||
<span
|
||||
class="font-semibold bg-gradient-to-tr from-pink-700 dark:from-indigo-400 via-purple-700 dark:via-purple-400 to-indigo-700 dark:to-indigo-400 text-transparent bg-clip-text">
|
||||
@{{ username }}
|
||||
</span>
|
||||
<span class="text-muted-foreground">{{ instance && "@" }}{{ instance }}</span>
|
||||
</CopyableText>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="flex p-2 items-center justify-center h-12">
|
||||
<Loader class="size-4 animate-spin" />
|
||||
</div>
|
||||
<div v-else-if="relationship?.requested_by === false" class="flex p-2 items-center justify-center h-12">
|
||||
<Check class="size-4" />
|
||||
</div>
|
||||
<div v-else class="grid grid-cols-2 p-2 gap-2">
|
||||
<Button variant="outline" size="sm" @click="accept">
|
||||
<Check />
|
||||
Accept
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" @click="reject">
|
||||
<X />
|
||||
Reject
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Account } from "@versia/client/types";
|
||||
import { Check, Loader, X } from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
|
||||
import { Button } from "~/components/ui/button";
|
||||
|
||||
const { follower } = defineProps<{
|
||||
follower: Account;
|
||||
}>();
|
||||
|
||||
const loading = ref(true);
|
||||
const [username, instance] = follower.acct.split("@");
|
||||
const { relationship } = useRelationship(client, follower.id);
|
||||
|
||||
// TODO: Add "followed" notification
|
||||
watch(relationship, () => {
|
||||
if (relationship.value) {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
const accept = async () => {
|
||||
const id = toast.loading("Accepting follow request...");
|
||||
loading.value = true;
|
||||
|
||||
const { data } = await client.value.acceptFollowRequest(follower.id);
|
||||
|
||||
toast.dismiss(id);
|
||||
toast.success("Follow request accepted.");
|
||||
relationship.value = data;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const reject = async () => {
|
||||
const id = toast.loading("Rejecting follow request...");
|
||||
loading.value = true;
|
||||
|
||||
const { data } = await client.value.rejectFollowRequest(follower.id);
|
||||
|
||||
toast.dismiss(id);
|
||||
toast.success("Follow request rejected.");
|
||||
relationship.value = data;
|
||||
loading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,32 +1,45 @@
|
|||
<template>
|
||||
<TooltipProvider>
|
||||
<Card>
|
||||
<Card>
|
||||
<Collapsible>
|
||||
<Tooltip>
|
||||
<TooltipTrigger :as-child="true">
|
||||
<CardHeader v-if="notification.account" class="flex-row items-center gap-2 p-4">
|
||||
<component :is="icon" class="size-5" />
|
||||
<CardHeader v-if="notification.account"
|
||||
class="flex-row items-center gap-2 px-4 py-2 border-b border-border">
|
||||
<component :is="icon" class="size-5 shrink-0" />
|
||||
<Avatar class="size-6 rounded-md border border-card">
|
||||
<AvatarImage :src="notification.account.avatar" alt="" />
|
||||
<AvatarFallback class="rounded-lg"> AA </AvatarFallback>
|
||||
</Avatar>
|
||||
<span class="font-semibold">{{ notification.type === 'mention' ? text.toLowerCase() : notification.account.display_name }}</span>
|
||||
<span class="font-semibold">{{
|
||||
notification.account.display_name
|
||||
}}</span>
|
||||
<CollapsibleTrigger :as-child="true">
|
||||
<Button variant="ghost" size="icon" class="ml-auto [&_svg]:data-[state=open]:-rotate-180">
|
||||
<ChevronDown class="duration-200" />
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</CardHeader>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{{ text }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<CardContent class="p-0">
|
||||
<Note v-if="notification.status" :note="notification.status" :small-layout="true" :hide-actions="true" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TooltipProvider>
|
||||
<CollapsibleContent :as-child="true">
|
||||
<CardContent class="p-0">
|
||||
<Note v-if="notification.status" :note="notification.status" :small-layout="true"
|
||||
:hide-actions="true" />
|
||||
<FollowRequest v-else-if="notification.type === 'follow_request' && notification.account" :follower="notification.account" />
|
||||
</CardContent>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Notification } from "@versia/client/types";
|
||||
import {
|
||||
AtSign,
|
||||
ChevronDown,
|
||||
Heart,
|
||||
Repeat,
|
||||
User,
|
||||
|
|
@ -34,14 +47,20 @@ import {
|
|||
UserPlus,
|
||||
} from "lucide-vue-next";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "~/components/ui/card";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "~/components/ui/collapsible";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "~/components/ui/tooltip";
|
||||
import Note from "../notes/note.vue";
|
||||
import FollowRequest from "./follow-request.vue";
|
||||
|
||||
const { notification } = defineProps<{
|
||||
notification: Notification;
|
||||
|
|
@ -84,4 +103,4 @@ const text = computed(() => {
|
|||
return "";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue