Skip to content
Open
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
28 changes: 7 additions & 21 deletions VueApp/src/Effort/components/AddCourseEffortDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,27 +145,12 @@
</q-form>
</q-card-section>

<q-card-actions align="right">
<q-btn
flat
label="Cancel"
@click="handleClose"
/>
<q-btn
color="primary"
label="Add Effort"
:loading="isSaving"
@click="createRecord"
>
<template #loading>
<q-spinner
size="1em"
class="q-mr-sm"
/>
Add Effort
</template>
</q-btn>
</q-card-actions>
<DialogSubmitActions
submit-label="Add Effort"
:is-saving="isSaving"
@cancel="handleClose"
@submit="createRecord"
/>
</q-card>
</q-dialog>
</template>
Expand All @@ -178,6 +163,7 @@ import { courseService } from "../services/course-service"
import { recordService } from "../services/record-service"
import type { CourseInstructorOptionDto, EffortTypeOptionDto, RoleOptionDto } from "../types"
import StatusBanner from "@/components/StatusBanner.vue"
import DialogSubmitActions from "./DialogSubmitActions.vue"
import { filterEffortTypesByCourse } from "../utils/effort-type-filters"
import { effortValueRules, requiredRule, notesMaxHint } from "../validation"
import "../effort-dialogs.css"
Expand Down
137 changes: 137 additions & 0 deletions VueApp/src/Effort/components/AsyncOperationDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<script setup lang="ts">
withDefaults(
defineProps<{
modelValue: boolean
title: string
subtitle?: string
maxWidth?: string
isLoading: boolean
isCommitting: boolean
loadError?: string | null
progress?: number
progressTitle?: string
progressPhase?: string
progressDetail?: string
progressColor?: string
loadingMessage?: string
}>(),
{
subtitle: undefined,
maxWidth: "1000px",
loadError: null,
progress: 0,
progressTitle: "",
progressPhase: "",
progressDetail: "",
progressColor: "primary",
loadingMessage: "Generating preview...",
},
)

defineEmits<{
retry: []
close: []
}>()
</script>

<template>
<q-dialog
:model-value="modelValue"
persistent
maximized-on-mobile
aria-labelledby="async-operation-dialog-title"
@keydown.escape="$emit('close')"
>
<q-card :style="`width: 100%; max-width: ${maxWidth}; position: relative`">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove inline styles.

Lines 45 and 52 use inline style attributes. Prefer Quasar utility classes or define styles in a <style scoped> block. As per coding guidelines, no inline styles are allowed.

♻️ Proposed fix

For line 45, use :style binding or move to scoped styles:

-        <q-card :style="`width: 100%; max-width: ${maxWidth}; position: relative`">
+        <q-card 
+            class="full-width"
+            :style="{ maxWidth, position: 'relative' }"
+        >

For line 52, move z-index to scoped styles:

-                style="z-index: 1"

Add to <style scoped> block at the end of the file:

<style scoped>
.absolute-top-right {
    z-index: 1;
}
</style>

Also applies to: 52-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@VueApp/src/Effort/components/AsyncOperationDialog.vue` at line 45, Remove the
inline style attributes on the QCard and the element at the top-right: replace
the :style binding on the q-card (the element using `:style="`width: 100%;
max-width: ${maxWidth}; position: relative`"`) with a class (e.g.,
`async-op-card`) and move the top-right element's inline z-index style into a
class (e.g., `absolute-top-right`); then add those CSS rules in the component's
<style scoped> block (set width/ max-width/position rules for `.async-op-card`
and z-index/positioning for `.absolute-top-right`) and update the template to
use the new class names or Quasar utility classes instead of inline styles.

<q-btn
icon="close"
flat
round
dense
class="absolute-top-right q-ma-sm"
style="z-index: 1"
aria-label="Close dialog"
@click="$emit('close')"
/>
<q-card-section class="q-pb-none q-pr-xl">
<div
id="async-operation-dialog-title"
class="text-h6"
>
{{ title }}
</div>
<div
v-if="subtitle"
class="text-caption text-grey-7"
>
{{ subtitle }}
</div>
</q-card-section>

<slot name="before-body" />

<!-- Loading State (Preview) -->
<q-card-section
v-if="isLoading"
class="text-center q-py-xl"
>
<q-spinner-dots
size="50px"
color="primary"
/>
<div class="q-mt-md text-grey-7">{{ loadingMessage }}</div>
</q-card-section>

<!-- Committing State (Progress) -->
<q-card-section
v-else-if="isCommitting"
class="q-py-xl"
>
<div class="text-h6 q-mb-md text-center">{{ progressTitle }}</div>
<q-linear-progress
:value="progress"
size="25px"
:color="progressColor"
class="q-mb-md"
>
<div class="absolute-full flex flex-center">
<q-badge
color="white"
:text-color="progressColor"
:label="`${Math.round(progress * 100)}%`"
/>
</div>
</q-linear-progress>
<div class="text-center text-grey-7">{{ progressPhase }}</div>
<div
v-if="progressDetail"
class="text-center text-caption text-grey-6 q-mt-xs"
>
{{ progressDetail }}
</div>
</q-card-section>

<!-- Error State -->
<q-card-section
v-else-if="loadError"
class="text-center q-py-xl"
>
<q-icon
name="error"
color="negative"
size="48px"
/>
<div class="q-mt-md text-negative">{{ loadError }}</div>
<q-btn
label="Retry"
color="primary"
class="q-mt-md"
@click="$emit('retry')"
/>
</q-card-section>

<!-- Preview content -->
<slot v-else />
</q-card>
</q-dialog>
</template>
Loading