fix(app): resolve Bucket B (type safety) lint items

WS-3 session 1b-ii Task 3 (audit Bucket B — 34 items: 21 absorbed
via ignorePatterns + 14 real fixes; the count of 21 is the actual
non-Tier-3 lint-count drop from the .eslintrc edit, slightly above
the audit's predicted 20 because additional vendored-Vuexy items
beyond the 23 no-explicit-any landed in those paths too).

Config:
- .eslintrc.cjs: add src/@core/** and src/@layouts/** to ignorePatterns.
  Vendored Vuexy code, precedent: src/plugins/iconify/*.js. The
  CLAUDE.md no-any rule remains in force for our own code under src/.

Real type-safety fixes:
- B.1 ref<any> in our code (3 occurrences):
  * blank.vue / default.vue: AppLoadingIndicator template ref now
    typed as InstanceType<typeof AppLoadingIndicator> | null. Picks
    up the defineExpose'd fallbackHandle / resolveHandle methods.
  * NavSearchBar.vue:109: useApi<any>(...) → useApi<SearchResults[]>(...)
    matching the existing searchResult ref type.
- B.2 ShiftDetailPanel.vue: moved the Cancel-dialog ref declarations
  (isCancelDialogOpen, cancellingAssignment) from line 305-307 to
  line 248 — directly above the onCancel handler that uses them.
  Resolves all 7 no-use-before-define items in one move. Same-file,
  no logic change.
- B.3 useImpersonationStore.ts:119: renamed inner 'stored' to
  'storedSnapshot' to resolve shadowing of the outer 'stored' on
  line 18.
- B.4 useFormSchemas.ts:97-99: renamed local mutationFn parameter
  'confirmed_name' to camelCase 'confirmedName'. Wire-format key
  stays snake_case via destructure-alias:
    params: confirmedName ? { confirmed_name: confirmedName } : undefined
  No callers found in apps/app/src — safe rename.

Tests + typecheck verified green.

Lint baseline: 97 → 62.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-29 14:11:05 +02:00
parent dcb8d53b61
commit d407cd17de
7 changed files with 17 additions and 12 deletions

View File

@@ -245,6 +245,10 @@ function executeApprove(assignment: ShiftAssignment) {
})
}
// Cancel dialog
const isCancelDialogOpen = ref(false)
const cancellingAssignment = ref<ShiftAssignment | null>(null)
function onCancel(assignment: ShiftAssignment) {
cancellingAssignment.value = assignment
isCancelDialogOpen.value = true
@@ -302,10 +306,6 @@ function onRejectExecute() {
)
}
// Cancel dialog
const isCancelDialogOpen = ref(false)
const cancellingAssignment = ref<ShiftAssignment | null>(null)
// Bulk approve dialog
const isBulkApproveDialogOpen = ref(false)

View File

@@ -94,9 +94,9 @@ export function useDeleteFormSchema(orgId: Ref<string>) {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async ({ id, confirmed_name }: { id: string; confirmed_name?: string }) => {
mutationFn: async ({ id, confirmedName }: { id: string; confirmedName?: string }) => {
await apiClient.delete(`/organisations/${orgId.value}/forms/schemas/${id}`, {
params: confirmed_name ? { confirmed_name } : undefined,
params: confirmedName ? { confirmed_name: confirmedName } : undefined,
})
},
onSuccess: () => {

View File

@@ -1,4 +1,6 @@
<script lang="ts" setup>
import type AppLoadingIndicator from '@/components/AppLoadingIndicator.vue'
const { injectSkinClasses } = useSkins()
// This will inject classes in body tag for accurate styling
@@ -6,7 +8,7 @@ injectSkinClasses()
// SECTION: Loading Indicator
const isFallbackStateActive = ref(false)
const refLoadingIndicator = ref<any>(null)
const refLoadingIndicator = ref<InstanceType<typeof AppLoadingIndicator> | null>(null)
// watching if the fallback state is active and the refLoadingIndicator component is available
watch([isFallbackStateActive, refLoadingIndicator], () => {

View File

@@ -106,7 +106,7 @@ const searchResult = ref<SearchResults[]>([])
const fetchResults = async () => {
isLoading.value = true
const { data } = await useApi<any>(withQuery('/app-bar/search', { q: searchQuery.value }))
const { data } = await useApi<SearchResults[]>(withQuery('/app-bar/search', { q: searchQuery.value }))
searchResult.value = data.value

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup>
import type AppLoadingIndicator from '@/components/AppLoadingIndicator.vue'
import { useConfigStore } from '@core/stores/config'
import { AppContentLayoutNav } from '@layouts/enums'
import { switchToVerticalNavOnLtOverlayNavBreakpoint } from '@layouts/utils'
@@ -18,7 +19,7 @@ injectSkinClasses()
// SECTION: Loading Indicator
const isFallbackStateActive = ref(false)
const refLoadingIndicator = ref<any>(null)
const refLoadingIndicator = ref<InstanceType<typeof AppLoadingIndicator> | null>(null)
// watching if the fallback state is active and the refLoadingIndicator component is available
watch([isFallbackStateActive, refLoadingIndicator], () => {

View File

@@ -116,10 +116,10 @@ export const useImpersonationStore = defineStore('impersonation', () => {
}
function restoreFromStorage(): void {
const stored = sessionStorage.getItem(SESSION_STORAGE_KEY)
if (stored) {
const storedSnapshot = sessionStorage.getItem(SESSION_STORAGE_KEY)
if (storedSnapshot) {
try {
state.value = JSON.parse(stored) as ImpersonationState
state.value = JSON.parse(storedSnapshot) as ImpersonationState
}
catch {
sessionStorage.removeItem(SESSION_STORAGE_KEY)