Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/atrium-telegram/app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ watch(colorMode, () => {
// Init Stores
const user = useUserStore()
const task = useTaskStore()
const epic = useEpicStore()

// Guard
await user.update()
Expand All @@ -72,13 +73,15 @@ onMounted(async () => {
user.updateOnline(),
user.update(),
task.update(),
epic.update(),
])

interval = setInterval(async () => {
await Promise.all([
user.updateOnline(),
user.update(),
task.update(),
epic.update(),
])
}, 30000)
Comment on lines 79 to 86
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Harden periodic updates and avoid type pitfall for interval handle.

  • Same resilience issue as above.
  • In browser, prefer ReturnType over NodeJS.Timeout to avoid TS friction.

Apply:

-  interval = setInterval(async () => {
-    await Promise.all([
+  interval = setInterval(async () => {
+    await Promise.allSettled([
       user.updateOnline(),
       user.update(),
       task.update(),
       epic.update(),
     ])
   }, 30000)

Additionally (outside this hunk), change the declaration:

// Before: let interval: NodeJS.Timeout
let interval: ReturnType<typeof setInterval>

🏁 Script executed:

#!/bin/bash
rg -n "let interval" -C3 apps/atrium-telegram/app/app.vue

Length of output: 181


Harden periodic updates and use correct interval type
Replace Promise.all with Promise.allSettled in the interval callback so one failed update doesn’t cancel the others, and change the interval’s declaration from NodeJS.Timeout to the browser-compatible ReturnType<typeof setInterval>.

--- a/apps/atrium-telegram/app/app.vue
@@ -79,7 +79,7 @@ onMounted(async () => {
   interval = setInterval(async () => {
-    await Promise.all([
+    await Promise.allSettled([
       user.updateOnline(),
       user.update(),
       task.update(),
       epic.update(),
     ])
   }, 30000)

And at line 69:

- let interval: NodeJS.Timeout
+ let interval: ReturnType<typeof setInterval>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
interval = setInterval(async () => {
await Promise.all([
user.updateOnline(),
user.update(),
task.update(),
epic.update(),
])
}, 30000)
// use a browser-compatible timer handle
let interval: ReturnType<typeof setInterval>
onMounted(async () => {
// use allSettled so one rejection doesn’t short-circuit the rest
interval = setInterval(async () => {
await Promise.allSettled([
user.updateOnline(),
user.update(),
task.update(),
epic.update(),
])
}, 30000)
})
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/app.vue around lines 69 and 79-86, the periodic
update uses Promise.all and the interval is typed as NodeJS.Timeout which is not
browser-compatible; change the interval variable's type from NodeJS.Timeout to
ReturnType<typeof setInterval> (at/near line 69) and replace Promise.all with
Promise.allSettled inside the setInterval callback so one rejection doesn't
cancel the other updates; after awaiting Promise.allSettled, optionally inspect
results and log or handle rejected entries to surface failures without breaking
the other updates.

})
Expand Down
11 changes: 11 additions & 0 deletions apps/atrium-telegram/app/components/ActiveCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<div class="relative active:scale-90 duration-200 motion-preset-slide-left" @click="vibrate()">
<Section>
<slot />
</Section>
</div>
Comment on lines +2 to +6
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make the clickable wrapper accessible (keyboard + ARIA).

The root div is clickable but not keyboard-accessible. Add role/tabindex and handle Enter/Space.

-  <div class="relative active:scale-90 duration-200 motion-preset-slide-left" @click="vibrate()">
+  <div
+    role="button"
+    tabindex="0"
+    class="relative active:scale-90 duration-200 motion-preset-slide-left"
+    @click="vibrate()"
+    @keydown.enter.prevent="vibrate()"
+    @keydown.space.prevent="vibrate()"
+  >
     <Section>
       <slot />
     </Section>
   </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class="relative active:scale-90 duration-200 motion-preset-slide-left" @click="vibrate()">
<Section>
<slot />
</Section>
</div>
<div
role="button"
tabindex="0"
class="relative active:scale-90 duration-200 motion-preset-slide-left"
@click="vibrate()"
@keydown.enter.prevent="vibrate()"
@keydown.space.prevent="vibrate()"
>
<Section>
<slot />
</Section>
</div>
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/ActiveCard.vue around lines 2 to 6, the
root div is clickable but not keyboard-accessible; add accessibility attributes
and keyboard handling by giving the div role="button" and tabindex="0" and
wiring a keydown handler that invokes the same vibrate() method when Enter or
Space are pressed (for Space, prevent default to avoid page scroll); keep the
existing @click handler and ensure any ARIA label/aria-labelledby is provided by
the consumer if necessary.

</template>

<script setup lang="ts">
const { vibrate } = useFeedback()
</script>
2 changes: 1 addition & 1 deletion apps/atrium-telegram/app/components/CreateCard.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="flex flex-col gap-4 justify-center items-center h-full min-h-40 border-2 border-default border-dashed rounded-lg">
<div class="flex flex-col gap-4 justify-center items-center h-full min-h-32 border-2 border-default border-dashed rounded-lg">
<UIcon :name="icon" class="size-10 text-muted/50" />

<UButton
Expand Down
38 changes: 38 additions & 0 deletions apps/atrium-telegram/app/components/EpicCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<ActiveCard class="w-full flex flex-col gap-3.5">
<UIcon name="i-lucide-crown" class="size-8 text-primary" />

<h3 class="text-lg/5 font-bold">
{{ epic.title }}
</h3>

<div class="w-full text-base/5 text-muted/50 whitespace-pre-wrap break-words line-clamp-3">
{{ epic.description }}
</div>

<div class="flex justify-between items-center">
<div class="flex flex-row gap-4">
<div class="flex flex-row gap-1.5 items-center text-muted">
<UIcon name="i-lucide-message-circle" class="size-5" />
<p>{{ epic?.comments.length }}</p>
</div>
</div>

<time
:datetime="epic.createdAt"
class="text-sm text-muted"
v-text="format(new Date(epic.createdAt), 'от d MMMM yyyy', { locale: ru })"
/>
Comment on lines +21 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Escape literal text in date-fns format string.

'o' is a token; without quotes you'll get incorrect output. Wrap "от" in quotes.

-        v-text="format(new Date(epic.createdAt), 'от d MMMM yyyy', { locale: ru })"
+        v-text="format(new Date(epic.createdAt), `'от' d MMMM yyyy`, { locale: ru })"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<time
:datetime="epic.createdAt"
class="text-sm text-muted"
v-text="format(new Date(epic.createdAt), 'от d MMMM yyyy', { locale: ru })"
/>
<time
:datetime="epic.createdAt"
class="text-sm text-muted"
v-text="format(
new Date(epic.createdAt),
`'от' d MMMM yyyy`,
{ locale: ru }
)"
/>
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/EpicCard.vue around lines 21 to 25, the
date-fns format string uses unquoted literal text "от" which will be interpreted
as a token; update the format string to escape the literal by wrapping it in
quotes (e.g. "'от' d MMMM yyyy") so the word "от" is rendered literally when
formatting epic.createdAt.

</div>
</ActiveCard>
</template>

<script setup lang="ts">
import type { EpicWithData } from '~/stores/epic'
import { format } from 'date-fns'
import { ru } from 'date-fns/locale/ru'
Comment on lines +32 to +33
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix date-fns locale import (named import from locale/ru is invalid).

Use the default export from 'date-fns/locale/ru' to avoid runtime undefined.

-import { format } from 'date-fns'
-import { ru } from 'date-fns/locale/ru'
+import { format } from 'date-fns'
+import ru from 'date-fns/locale/ru'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { format } from 'date-fns'
import { ru } from 'date-fns/locale/ru'
import { format } from 'date-fns'
import ru from 'date-fns/locale/ru'
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/EpicCard.vue around lines 32-33, the code
uses a named import for the Russian locale (import { ru } from
'date-fns/locale/ru') which is invalid and yields undefined at runtime; change
it to use the default import (import ru from 'date-fns/locale/ru') and keep
passing ru to format/locale options, ensuring any references to ru remain the
same.


defineProps<{
epic: EpicWithData
}>()
</script>
106 changes: 106 additions & 0 deletions apps/atrium-telegram/app/components/EpicComment.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<template>
<UDropdownMenu
:items="items"
:ui="{
content: 'w-48',
}"
:content="{
sideOffset: -12,
}"
>
<UButton
color="neutral"
variant="link"
active
:ui="{
base: 'p-0',
}"
class="group/message relative text-left scroll-mt-4 motion-preset-slide-down-right"
>
<div class="min-w-[60%] relative flex items-start gap-2 pb-2 rtl:justify-end">
<div class="inline-flex items-center justify-center min-h-6 mt-1.5">
<UAvatar :src="user?.avatarUrl ?? undefined" />
</div>

<div class="min-h-12 w-full bg-elevated/25 px-3.5 py-2 flex flex-col gap-2.5 rounded-lg ring ring-default">
<div class="flex flex-col gap-1">
<div v-if="comment?.createdAt" class="mt-1 flex justify-start text-xs text-dimmed">
{{ format(new Date(comment.createdAt), 'dd MMMM в HH:mm', { locale: ru }) }}
</div>

<div class="text-sm/4 whitespace-break-spaces text-default text-pretty font-medium">
{{ comment?.text }}
</div>
</div>

<div v-if="comment?.notifications?.length" class="flex flex-row flex-wrap gap-1">
<UserBeacon
v-for="notification in comment.notifications"
:key="notification.id"
:notification="notification"
/>
</div>
</div>
</div>
</UButton>
</UDropdownMenu>
</template>

<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'
import { ModalCreateEpicCommentBeacon } from '#components'
import { format } from 'date-fns'
import { ru } from 'date-fns/locale/ru'

Comment on lines +52 to +54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix date-fns locale import (named import from locale/ru is invalid).

Same issue as in EpicCard.vue.

-import { format } from 'date-fns'
-import { ru } from 'date-fns/locale/ru'
+import { format } from 'date-fns'
+import ru from 'date-fns/locale/ru'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { format } from 'date-fns'
import { ru } from 'date-fns/locale/ru'
import { format } from 'date-fns'
import ru from 'date-fns/locale/ru'
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/EpicComment.vue around lines 52-54 the
locale import from date-fns is wrong: change the named import "import { ru }
from 'date-fns/locale/ru'" to a default import "import ru from
'date-fns/locale/ru'" (same fix used in EpicCard.vue) and ensure any format
calls pass the locale as { locale: ru }.

const { epicId, commentId } = defineProps<{
epicId: string
commentId: string
}>()

const overlay = useOverlay()
const modalCreateEpicCommentBeacon = overlay.create(ModalCreateEpicCommentBeacon)

const epicStore = useEpicStore()
const userStore = useUserStore()

const epic = computed(() => epicStore.epics.find((epic) => epic.id === epicId))
const comment = computed(() => epic.value?.comments.find((comment) => comment.id === commentId))
const user = computed(() => userStore.find(comment.value?.userId ?? ''))

const items = computed<DropdownMenuItem[]>(() => {
const menuItems: DropdownMenuItem[] = [
{
label: 'Маякнуть',
icon: 'i-lucide-users-round',
color: 'neutral',
disabled: false,
onSelect: () => modalCreateEpicCommentBeacon.open({ commentId }),
condition: true,
},
{
label: 'Поставить лайк',
icon: 'i-lucide-thumbs-up',
color: 'neutral',
disabled: true,
onSelect: () => {},
condition: user.value?.id !== userStore.id,
},
{
label: 'Редактировать',
icon: 'i-lucide-edit',
disabled: true,
onSelect: () => {},
condition: user.value?.id === userStore.id,
},
{
label: 'Удалить',
icon: 'i-lucide-trash-2',
disabled: true,
onSelect: () => {},
condition: user.value?.id === userStore.id,
},
]

return menuItems.filter((item) => item.condition)
})
</script>
5 changes: 3 additions & 2 deletions apps/atrium-telegram/app/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
<div
class="relative py-1 w-full rounded-2xl flex flex-row items-center justify-center"
:class="[
router.currentRoute.value.path === route.path && 'tg-bg-button tg-text-button motion-translate-y-in',
(route.exact ? router.currentRoute.value.path === route.path : router.currentRoute.value.path.startsWith(route.path)) && 'tg-bg-button tg-text-button motion-translate-y-in',
]"
Comment on lines +14 to 15
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid over-highlighting routes when using startsWith.

/epic will also match /epic-admin. Use stricter prefix logic (exact or path === route.path || path.startsWith(route.path + '/')). Also DRY by extracting to a helper.

-              (route.exact ? router.currentRoute.value.path === route.path : router.currentRoute.value.path.startsWith(route.path)) && 'tg-bg-button tg-text-button motion-translate-y-in',
+              isActive(route) && 'tg-bg-button tg-text-button motion-translate-y-in',

Add once in <script setup>:

const isActive = (route: { path: string; exact?: boolean }) => {
  const path = router.currentRoute.value.path
  return route.exact ? path === route.path : (path === route.path || path.startsWith(route.path + '/'))
}
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/Navigation.vue around lines 14-15, the
current startsWith check over-highlights routes (e.g. "/epic" matches
"/epic-admin"); extract a helper in <script setup> (e.g. isActive(route)) that
reads router.currentRoute.value.path and returns route.exact ? path ===
route.path : (path === route.path || path.startsWith(route.path + '/')); then
replace the inline expression in the template with a call to that helper to make
matching stricter and avoid duplicated logic.

>
<UIcon :name="route.icon" class="size-6" />
</div>
<p
class="text-xs font-medium"
:class="[
router.currentRoute.value.path === route.path && 'tg-text',
(route.exact ? router.currentRoute.value.path === route.path : router.currentRoute.value.path.startsWith(route.path)) && 'tg-text',
]"
>
{{ route.title }}
Expand All @@ -41,6 +41,7 @@ const mainRoutes = computed(() => [
name: 'home',
title: t('app.home'),
icon: 'i-lucide-layout-dashboard',
exact: true,
},
{
path: '/epic',
Expand Down
2 changes: 1 addition & 1 deletion apps/atrium-telegram/app/components/PageContainer.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="z-30 overflow-hidden h-full min-h-dvh w-full tg-content-safe-area">
<div class="px-4 py-2 max-w-[28rem] mx-auto flex flex-col gap-y-6">
<div class="px-4 py-2 max-w-[28rem] mx-auto mb-20 flex flex-col gap-y-6">
<slot />
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions apps/atrium-telegram/app/components/Section.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<div class="p-4 tg-bg-section group/section space-y-3.5 rounded-lg">
<slot />
</div>
</template>
2 changes: 1 addition & 1 deletion apps/atrium-telegram/app/components/TaskCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}"
:ui="{
content: 'w-48',
item: 'p-2',
item: 'p-2 motion-preset-slide-left motion-duration-200',
}"
>
<UButton
Expand Down
4 changes: 2 additions & 2 deletions apps/atrium-telegram/app/components/TaskList.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="p-4 rounded-lg tg-bg-section group/list space-y-3.5">
<Section>
<div class="flex flex-row gap-2 items-center justify-between">
<div class="flex flex-row gap-2.5 items-center">
<UPopover
Expand Down Expand Up @@ -87,7 +87,7 @@
Активных задач нет
</p>
</template>
</div>
</Section>
</template>

<script setup lang="ts">
Expand Down
71 changes: 71 additions & 0 deletions apps/atrium-telegram/app/components/form/CreateEpicComment.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<UCard
variant="subtle"
class="mt-auto bg-elevated/25"
>
<form
class="flex flex-col gap-4"
@submit.prevent="onCommentSubmit"
>
<UTextarea
v-model="text"
color="neutral"
variant="none"
size="xl"
required
autoresize
placeholder="Напишите свою мысль..."
:rows="3"
:disabled="loading"
class="w-full"
:ui="{ base: 'p-1' }"
/>

<div class="flex items-center justify-end gap-2">
<UButton
type="submit"
color="secondary"
size="md"
:loading="loading"
:disabled="!text"
label="Добавить комментарий"
icon="i-lucide-send"
:ui="{
base: 'px-3 rounded-full',
label: 'font-medium',
}"
/>
Comment on lines +25 to +37
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Prevent whitespace-only submits and disable while loading; localize button label.

Disabling on trimmed text avoids empty comments.

       <div class="flex items-center justify-end gap-2">
         <UButton
           type="submit"
           color="secondary"
           size="md"
           :loading="loading"
-          :disabled="!text"
-          label="Добавить комментарий"
+          :disabled="!text?.trim() || loading"
+          :label="$t('epic.comment.add')"
           icon="i-lucide-send"
           :ui="{
             base: 'px-3 rounded-full',
             label: 'font-medium',
           }"
         />
       </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<UButton
type="submit"
color="secondary"
size="md"
:loading="loading"
:disabled="!text"
label="Добавить комментарий"
icon="i-lucide-send"
:ui="{
base: 'px-3 rounded-full',
label: 'font-medium',
}"
/>
<div class="flex items-center justify-end gap-2">
<UButton
type="submit"
color="secondary"
size="md"
:loading="loading"
:disabled="!text?.trim() || loading"
:label="$t('epic.comment.add')"
icon="i-lucide-send"
:ui="{
base: 'px-3 rounded-full',
label: 'font-medium',
}"
/>
</div>

</div>
</form>
</UCard>
</template>

<script setup lang="ts">
const { epicId } = defineProps<{ epicId: string }>()

const { vibrate } = useFeedback()
const epicStore = useEpicStore()

const text = ref('')
const loading = ref(false)

async function onCommentSubmit() {
const trimmed = text.value.trim()
if (!trimmed) {
return
}

loading.value = true

try {
await epicStore.addComment(epicId, trimmed)
text.value = ''
vibrate('success')
} catch (e) {
console.error(e)
vibrate('error')
} finally {
loading.value = false
}
}
</script>
11 changes: 11 additions & 0 deletions apps/atrium-telegram/app/components/modal/CreateEpic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<UModal :title="$t('app.create.epic.title')">
<template #body>
<FormCreateEpic @submitted="overlay.closeAll" @success="overlay.closeAll" />
</template>
</UModal>
</template>

<script setup lang="ts">
const overlay = useOverlay()
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<UModal :title="$t('app.create.beacon.title')">
<template #body>
<FormCreateEpicCommentBeacon
:comment-id="commentId"
@submitted="overlay.closeAll"
@success="overlay.closeAll"
/>
</template>
</UModal>
</template>

<script setup lang="ts">
defineProps<{
commentId: string
}>()

const overlay = useOverlay()
</script>
19 changes: 19 additions & 0 deletions apps/atrium-telegram/app/components/modal/UpdateEpic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<UModal :title="$t('app.update.epic.title')">
<template #body>
<FormUpdateEpic
:epic-id="epicId"
@submitted="overlay.closeAll"
@success="overlay.closeAll"
/>
</template>
Comment on lines +4 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Don’t close the modal on “submitted”; close only on success.

Closing on submitted can hide failures and lose user input.

       <FormUpdateEpic
         :epic-id="epicId"
-        @submitted="overlay.closeAll"
-        @success="overlay.closeAll"
+        @success="overlay.closeAll"
       />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<FormUpdateEpic
:epic-id="epicId"
@submitted="overlay.closeAll"
@success="overlay.closeAll"
/>
</template>
<FormUpdateEpic
:epic-id="epicId"
@success="overlay.closeAll"
/>
</template>
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/modal/UpdateEpic.vue around lines 4–9,
the modal is being closed on the FormUpdateEpic "submitted" event which can hide
failures and lose user input; remove the @submitted="overlay.closeAll" binding
so the modal is closed only on the @success event, and ensure FormUpdateEpic
emits "success" only after a confirmed successful update (and that any logic
relying on "submitted" is updated to not close the overlay).

</UModal>
</template>

<script setup lang="ts">
defineProps<{
epicId: string
}>()

const overlay = useOverlay()
</script>
5 changes: 0 additions & 5 deletions apps/atrium-telegram/app/pages/epic.vue

This file was deleted.

Loading