Files
OpenSquawk/app/components/BugReportDialog.vue
itsrubberduck 034ddbab2e feat(bug-reports): trace reports by code and tell Live ATC from Classroom
Every report now gets a UUID that the notification mail quotes as
"Nenne den Fehlercode <uuid> beim Commit", so a fix can be tied back to
the report it closes. The mail also names the area it came from, and the
comment field is relabelled "Fehlerbeschreibung/Featurewunsch" since it
collects feature wishes just as often as bugs.

Classroom loses its plain feedback link and gets the same reporter as
Live ATC — screenshot, arrow annotation and all. `useBugReport` takes an
options object so the communications-engine snapshot stays optional; the
dialog moves out of `live-atc/cockpit` now that both pages use it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 21:11:43 +02:00

161 lines
5.8 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { useBugReport } from '~/composables/useBugReport'
/**
* The composable stays owned by the page: the HUD's "Report issue" button needs
* `openBugReport` and `bugReportCapturing` before this dialog ever renders. So it
* is handed over whole rather than unpacked into a dozen props.
*/
const props = defineProps<{
bug: ReturnType<typeof useBugReport>
theme: 'light' | 'dark'
}>()
const {
showBugReportDialog,
bugReportComment,
bugReportContact,
bugReportScreenshot,
bugReportArrows,
bugReportLoading,
bugReportError,
bugReportSuccess,
bugReportCode,
bugReportCanvasRef,
bugReportImgRef,
setupAnnotationCanvas,
onCanvasMouseDown,
onCanvasMouseMove,
onCanvasMouseUp,
onCanvasMouseLeave,
undoLastArrow,
submitBugReport,
} = props.bug
</script>
<template>
<v-dialog v-model="showBugReportDialog" max-width="680" scrollable :content-class="theme === 'light' ? 'pm-dialog-light' : ''">
<v-card :class="theme === 'light' ? 'bg-white border border-black/10 text-[#0f1420]' : 'bg-[#0b101d] border border-white/10 text-white'">
<v-card-title class="flex items-center gap-2 text-base font-semibold pt-4 px-5">
<v-icon icon="mdi-bug-outline" color="#f87171" size="20" />
Fehler melden
</v-card-title>
<v-card-text class="space-y-4 px-5 pb-2">
<div v-if="bugReportSuccess" class="rounded-xl bg-emerald-500/10 border border-emerald-400/30 p-4 text-center">
<v-icon icon="mdi-check-circle-outline" color="emerald" size="32" class="mb-2" />
<p class="text-emerald-300 font-semibold">Danke! Bug Report wurde gesendet.</p>
<p v-if="bugReportCode" class="mt-2 text-xs text-emerald-200/70">
Fehlercode <span class="font-mono">{{ bugReportCode }}</span>
</p>
</div>
<template v-else>
<div v-if="bugReportScreenshot" class="space-y-2">
<div class="flex items-start justify-between gap-3">
<div class="flex items-start gap-2">
<v-icon size="18" color="red" class="mt-0.5">mdi-gesture-tap-button</v-icon>
<div>
<p class="text-sm font-semibold text-white/90">Wo ist der Fehler? Zeichne einen Pfeil hin.</p>
<p class="text-xs text-white/55 leading-snug">
Klicke auf die Stelle und ziehe mit gedrückter Maustaste (am Handy: mit dem Finger)
zur Problemstelle. Du kannst mehrere Pfeile setzen.
</p>
</div>
</div>
<v-btn
v-if="bugReportArrows.length > 0"
size="x-small"
variant="text"
color="red"
prepend-icon="mdi-undo"
class="shrink-0"
@click="undoLastArrow"
>
Pfeil zurück
</v-btn>
</div>
<div class="relative rounded-xl overflow-hidden border border-white/10" style="line-height:0">
<img
ref="bugReportImgRef"
:src="bugReportScreenshot"
class="w-full block"
alt="Screenshot"
@load="setupAnnotationCanvas"
/>
<canvas
ref="bugReportCanvasRef"
class="absolute inset-0 w-full h-full cursor-crosshair select-none"
style="touch-action:none"
@pointerdown="onCanvasMouseDown"
@pointermove="onCanvasMouseMove"
@pointerup="onCanvasMouseUp"
@pointerleave="onCanvasMouseLeave"
@pointercancel="onCanvasMouseLeave"
/>
<span
v-if="bugReportArrows.length === 0"
class="pointer-events-none absolute inset-0 flex items-center justify-center text-center px-4"
>
<span class="rounded-full bg-black/55 px-3 py-1 text-xs text-white/85 backdrop-blur">
Hier ziehen, um einen Pfeil zur Fehlerstelle zu zeichnen
</span>
</span>
</div>
</div>
<div v-else class="rounded-xl border border-white/10 bg-white/5 p-4 text-center text-sm text-white/50">
Kein Screenshot verfügbar
</div>
<v-textarea
v-model="bugReportComment"
label="Fehlerbeschreibung / Featurewunsch"
placeholder="Was ist kaputt? Was sollte stattdessen passieren?"
persistent-placeholder
variant="outlined"
color="red"
rows="3"
auto-grow
maxlength="2000"
counter="2000"
hide-details="auto"
:disabled="bugReportLoading"
/>
<v-text-field
v-model="bugReportContact"
label="Dein Name / Kontakt"
variant="outlined"
color="red"
density="comfortable"
hide-details
:disabled="bugReportLoading"
/>
<v-alert
v-if="bugReportError"
type="error"
density="compact"
variant="tonal"
class="bg-red-500/10 text-red-200"
>
{{ bugReportError }}
</v-alert>
</template>
</v-card-text>
<v-card-actions v-if="!bugReportSuccess" class="justify-end gap-2 px-5 pb-4">
<v-btn variant="text" color="grey" :disabled="bugReportLoading" @click="showBugReportDialog = false">
Abbrechen
</v-btn>
<v-btn
color="red"
variant="flat"
:loading="bugReportLoading"
:disabled="!bugReportComment.trim()"
@click="submitBugReport"
>
Bug melden
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>