Skip to content

Commit 8cd9e2e

Browse files
committed
feat: introduce surface variables
1 parent 518c7d1 commit 8cd9e2e

File tree

4 files changed

+195
-160
lines changed

4 files changed

+195
-160
lines changed

apps/frontend/src/components/ui/moderation/ModerationReportCard.vue

Lines changed: 107 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,123 @@
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"
@@ -130,7 +127,7 @@
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'
149142
import {
150143
Avatar,
151144
ButtonStyled,
@@ -157,7 +150,6 @@ import {
157150
} from '@modrinth/ui'
158151
import { computed } from 'vue'
159152
160-
import ChevronDownIcon from '../servers/icons/ChevronDownIcon.vue'
161153
import ReportThread from '../thread/ReportThread.vue'
162154
163155
const { 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-
228201
async function handleQuickReply(reply: ReportQuickReply) {
229202
const message =
230203
typeof reply.message === 'function' ? await reply.message(props.report) : reply.message

0 commit comments

Comments
 (0)