11<template >
2- <div class =" universal-card" >
3- <div
4- class =" flex w-full flex-col items-start justify-between gap-3 sm:flex-row sm:items-center sm:gap-0"
5- >
6- <span class =" text-md flex flex-col gap-2 sm:flex-row sm:items-center" >
7- <span class =" flex items-center gap-2" >
8- Reported for
9- <span class =" whitespace-nowrap rounded-full align-middle font-semibold text-contrast" >
10- {{ formattedReportType }}
2+ <div >
3+ <div class =" rounded-t-3xl bg-bg-raised p-4" >
4+ <div
5+ class =" flex w-full flex-col items-start justify-between gap-3 sm:flex-row sm:items-center sm:gap-0"
6+ >
7+ <span class =" text-md flex flex-col gap-2 sm:flex-row sm:items-center" >
8+ <span class =" flex items-center gap-2" >
9+ <span class =" text-secondary" >Reported for</span >
10+ <span
11+ class =" whitespace-nowrap rounded-full bg-button-bg px-2 py-0.5 align-middle text-xs font-semibold text-secondary"
12+ >
13+ {{ formattedReportType }}
14+ </span >
15+ </span >
16+ <span class =" flex items-center gap-2" >
17+ <span class =" hidden text-secondary sm:inline" >By</span >
18+ <span class =" text-secondary sm:hidden" >Reporter:</span >
19+ <nuxt-link
20+ :to =" `/user/${report.reporter_user.username}`"
21+ class =" inline-flex flex-row items-center gap-1 transition-colors duration-100 ease-in-out hover:text-brand"
22+ >
23+ <Avatar
24+ :src =" report.reporter_user.avatar_url"
25+ circle
26+ size =" 1.75rem"
27+ class =" flex-shrink-0"
28+ />
29+ <span class =" truncate" >{{ report.reporter_user.username }}</span >
30+ </nuxt-link >
1131 </span >
1232 </span >
13- <span class =" flex items-center gap-2" >
14- <span class =" hidden sm:inline" >By</span >
15- <span class =" sm:hidden" >Reporter:</span >
16- <nuxt-link
17- :to =" `/user/${report.reporter_user.username}`"
18- class =" inline-flex flex-row items-center gap-1 transition-colors duration-100 ease-in-out hover:text-brand"
19- >
20- <Avatar
21- :src =" report.reporter_user.avatar_url"
22- circle
23- size =" 1.75rem"
24- class =" flex-shrink-0"
25- />
26- <span class =" truncate" >{{ report.reporter_user.username }}</span >
27- </nuxt-link >
28- </span >
29- </span >
3033
31- <div class =" flex flex-row items-center gap-2 self-end sm:self-auto" >
32- <span class =" text-md whitespace-nowrap text-secondary" >{{
33- formatRelativeTime(report.created)
34- }}</span >
35- <ButtonStyled v-if =" visibleQuickReplies.length > 0" circular >
36- <OverflowMenu :options =" visibleQuickReplies" >
37- <span class =" hidden sm:inline" >Quick Reply</span >
38- <span class =" sr-only sm:hidden" >Quick Reply</span >
39- <ChevronDownIcon />
40- </OverflowMenu >
41- </ButtonStyled >
42- <ButtonStyled circular >
43- <OverflowMenu :options =" quickActions" >
44- <template #default >
45- <EllipsisVerticalIcon />
46- </template >
47- <template #copy-id >
48- <ClipboardCopyIcon />
49- <span class =" hidden sm:inline" >Copy ID</span >
50- </template >
51- <template #copy-link >
52- <LinkIcon />
53- <span class =" hidden sm:inline" >Copy link</span >
54- </template >
55- </OverflowMenu >
56- </ButtonStyled >
34+ <div class =" flex flex-row items-center gap-2 self-end sm:self-auto" >
35+ <span class =" whitespace-nowrap text-sm text-secondary" >{{
36+ formatRelativeTime(report.created)
37+ }}</span >
38+ <ButtonStyled circular >
39+ <OverflowMenu :options =" quickActions" >
40+ <template #default >
41+ <EllipsisVerticalIcon class =" size-4" />
42+ </template >
43+ <template #copy-id >
44+ <ClipboardCopyIcon />
45+ <span class =" hidden sm:inline" >Copy ID</span >
46+ </template >
47+ <template #copy-link >
48+ <LinkIcon />
49+ <span class =" hidden sm:inline" >Copy link</span >
50+ </template >
51+ </OverflowMenu >
52+ </ButtonStyled >
53+ </div >
5754 </div >
58- </div >
5955
60- <hr class =" my-4 rounded-xl border-solid text -divider" />
56+ <hr class =" my-4 border-t border -divider" />
6157
62- <div class =" flex flex-col gap-4" >
63- <div class =" flex flex-col gap-3 sm:flex-row sm:items-center" >
64- <div class =" flex min-w-0 flex-1 items-center gap-3" >
65- <Avatar
66- :src =" reportItemAvatarUrl"
67- :circle =" report.item_type === 'user'"
68- size =" 3rem"
69- class =" flex-shrink-0"
70- />
71- <div class =" min-w-0 flex-1" >
72- <span class =" block truncate text-lg font-semibold" >{{ reportItemTitle }}</span >
73- <div class =" flex flex-col gap-2 text-sm text-secondary sm:flex-row sm:items-center" >
74- <nuxt-link
75- v-if =" report.target && report.item_type != 'user'"
76- :to =" `/${report.target.type}/${report.target.slug}`"
77- class =" inline-flex flex-row items-center gap-1 truncate transition-colors duration-100 ease-in-out hover:text-brand"
78- >
79- <Avatar
80- :src =" report.target?.avatar_url"
81- :circle =" report.target.type === 'user'"
82- size =" 1rem"
83- class =" flex-shrink-0"
84- />
85- <span class =" truncate" >
86- <OrganizationIcon
87- v-if =" report.target.type === 'organization'"
88- class =" align-middle"
89- />
90- {{ report.target.name || 'Unknown User' }}
91- </span >
92- </nuxt-link >
93-
94- <div class =" flex flex-wrap items-center gap-2" >
95- <span
96- class =" whitespace-nowrap rounded-full bg-button-bg p-0.5 px-2 text-xs font-semibold text-secondary"
97- >
98- {{ formattedItemType }}
99- </span >
100- <span
101- v-if =" report.item_type === 'version' && report.version"
102- class =" max-w-[200px] truncate font-mono text-xs sm:max-w-none"
58+ <div class =" flex flex-col gap-4" >
59+ <div class =" flex flex-col gap-3 sm:flex-row sm:items-center" >
60+ <div class =" flex min-w-0 flex-1 items-center gap-3" >
61+ <Avatar
62+ :src =" reportItemAvatarUrl"
63+ :circle =" report.item_type === 'user'"
64+ size =" 3rem"
65+ class =" flex-shrink-0"
66+ />
67+ <div class =" min-w-0 flex-1" >
68+ <span class =" block truncate text-lg font-semibold" >{{ reportItemTitle }}</span >
69+ <div class =" flex flex-col gap-2 text-sm text-secondary sm:flex-row sm:items-center" >
70+ <nuxt-link
71+ v-if =" report.target && report.item_type != 'user'"
72+ :to =" `/${report.target.type}/${report.target.slug}`"
73+ class =" inline-flex flex-row items-center gap-1 truncate transition-colors duration-100 ease-in-out hover:text-brand"
10374 >
104- {{
105- report.version.files.find((file) => file.primary)?.filename || 'Unknown Version'
106- }}
107- </span >
75+ <Avatar
76+ :src =" report.target?.avatar_url"
77+ :circle =" report.target.type === 'user'"
78+ size =" 1rem"
79+ class =" flex-shrink-0"
80+ />
81+ <span class =" truncate" >
82+ <OrganizationIcon
83+ v-if =" report.target.type === 'organization'"
84+ class =" align-middle"
85+ />
86+ {{ report.target.name || 'Unknown User' }}
87+ </span >
88+ </nuxt-link >
89+
90+ <div class =" flex flex-wrap items-center gap-2" >
91+ <span
92+ class =" whitespace-nowrap rounded-full bg-button-bg px-2 py-0.5 text-xs font-semibold text-secondary"
93+ >
94+ {{ formattedItemType }}
95+ </span >
96+ <span
97+ v-if =" report.item_type === 'version' && report.version"
98+ class =" max-w-[200px] truncate font-mono text-xs sm:max-w-none"
99+ >
100+ {{
101+ report.version.files.find((file) => file.primary)?.filename ||
102+ 'Unknown Version'
103+ }}
104+ </span >
105+ </div >
108106 </div >
109107 </div >
110108 </div >
111- </div >
112109
113- <div class =" flex justify-end sm:justify-start" >
114- <ButtonStyled circular >
115- <nuxt-link :to =" reportItemUrl" >
116- <EyeIcon />
117- </nuxt-link >
118- </ButtonStyled >
110+ <div class =" flex justify-end sm:justify-start" >
111+ <ButtonStyled circular >
112+ <nuxt-link :to =" reportItemUrl" >
113+ <EyeIcon class =" size-4" />
114+ </nuxt-link >
115+ </ButtonStyled >
116+ </div >
119117 </div >
120118 </div >
121119 </div >
122-
123- <CollapsibleRegion ref =" collapsibleRegion" class =" my-4" >
120+ <div class =" border-1 bg-surface-l2 rounded-b-3xl border-solid border-bg-raised p-4" >
124121 <ReportThread
125122 v-if =" report.thread"
126123 ref =" reportThread"
130127 :reporter =" report.reporter_user"
131128 @update-thread =" updateThread"
132129 />
133- </CollapsibleRegion >
130+ </div >
134131 </div >
135132</template >
136133<script setup lang="ts">
@@ -141,11 +138,7 @@ import {
141138 LinkIcon ,
142139 OrganizationIcon ,
143140} from ' @modrinth/assets'
144- import {
145- type ExtendedReport ,
146- reportQuickReplies ,
147- type ReportQuickReply ,
148- } from ' @modrinth/moderation'
141+ import { type ExtendedReport , type ReportQuickReply } from ' @modrinth/moderation'
149142import {
150143 Avatar ,
151144 ButtonStyled ,
@@ -157,7 +150,6 @@ import {
157150} from ' @modrinth/ui'
158151import { computed } from ' vue'
159152
160- import ChevronDownIcon from ' ../servers/icons/ChevronDownIcon.vue'
161153import ReportThread from ' ../thread/ReportThread.vue'
162154
163155const { addNotification } = injectNotificationManager ()
@@ -206,25 +198,6 @@ const quickActions: OverflowMenuOption[] = [
206198 },
207199]
208200
209- const visibleQuickReplies = computed <OverflowMenuOption []>(() => {
210- return reportQuickReplies
211- .filter ((reply ) => {
212- if (reply .shouldShow === undefined ) return true
213- if (typeof reply .shouldShow === ' function' ) {
214- return reply .shouldShow (props .report )
215- }
216-
217- return reply .shouldShow
218- })
219- .map (
220- (reply ) =>
221- ({
222- id: reply .label ,
223- action : () => handleQuickReply (reply ),
224- }) as OverflowMenuOption ,
225- )
226- })
227-
228201async function handleQuickReply(reply : ReportQuickReply ) {
229202 const message =
230203 typeof reply .message === ' function' ? await reply .message (props .report ) : reply .message
0 commit comments