basic tempate of web

This commit is contained in:
2026-06-19 23:55:39 -07:00
parent cef6b487cd
commit 118472945f
172 changed files with 15878 additions and 0 deletions
@@ -0,0 +1,196 @@
<template>
<v-skeleton-loader
v-if="isNil(user)"
type="card"
/>
<HeaderActionsFormCard
v-else
ref="headerActionsFormCard"
title="User Details"
elevation="10"
@submit.prevent="saveWrapper"
>
<template #header-actions> </template>
<v-row>
<v-col
cols="12"
md="6"
>
<v-label class="mb-2">First name *</v-label>
<v-text-field
v-model="user.firstName"
hide-details="auto"
:rules="[required]"
required
/>
</v-col>
<v-col
cols="12"
md="6"
>
<v-label class="mb-2">Last name *</v-label>
<v-text-field
v-model="user.lastName"
hide-details="auto"
:rules="[required]"
required
/>
</v-col>
<v-col
cols="12"
md="6"
>
<v-label class="mb-2">Display name *</v-label>
<v-text-field
v-model="user.displayName"
hide-details="auto"
:rules="[required]"
required
/>
</v-col>
<v-col
cols="12"
md="6"
>
<v-label class="mb-2">Email</v-label>
<v-text-field
v-model="user.email"
type="email"
hide-details="auto"
:rules="[required, email]"
/>
</v-col>
<v-col
cols="12"
md="6"
>
<v-label class="mb-2">Roles</v-label>
<UserRoleSelect
v-model="user.roles"
hide-details="auto"
:rules="[required]"
/>
</v-col>
</v-row>
<template #actions>
<div class="d-flex mt-8">
<v-btn
:loading="isLoading"
color="primary"
type="submit"
>
Save User
</v-btn>
<v-spacer />
<v-btn
color="warning"
class="ml-4"
variant="outlined"
:loading="isLoading"
:to="{ name: 'administration/UsersPage' }"
>
Cancel
</v-btn>
<v-btn
v-if="canDelete"
color="error"
class="ml-4"
variant="outlined"
:loading="isDeleting"
@click="showDeleteDialog = true"
>
Delete
</v-btn>
</div>
</template>
</HeaderActionsFormCard>
<ConfirmDialog
v-model="showDeleteDialog"
title="Delete user?"
:message="`Permanently delete ${user?.displayName || user?.email}? This removes the user from all organizations and roles and cannot be undone.`"
confirm-text="Delete"
confirm-color="error"
@confirm="handleDelete"
/>
</template>
<script setup lang="ts">
import { computed, ref, toRefs } from "vue"
import { RouteLocationRaw, useRouter } from "vue-router"
import { isNil } from "lodash"
import { email, required } from "@/utils/validators"
import usersApi from "@/api/users-api"
import useCurrentUser from "@/use/use-current-user"
import useSnack from "@/use/use-snack"
import useUser from "@/use/use-user"
import ConfirmDialog from "@/components/common/ConfirmDialog.vue"
import HeaderActionsFormCard from "@/components/common/HeaderActionsFormCard.vue"
import UserRoleSelect from "@/components/users/UserRoleSelect.vue"
const props = withDefaults(
defineProps<{
userId: number
returnTo?: RouteLocationRaw
}>(),
{
returnTo: undefined,
}
)
const emit = defineEmits<{
saved: [userId: number]
}>()
const { userId } = toRefs(props)
const { user, policy, isLoading, save } = useUser(userId)
const { currentUser } = useCurrentUser()
const router = useRouter()
const headerActionsFormCard = ref<InstanceType<typeof HeaderActionsFormCard> | null>(null)
const snack = useSnack()
const showDeleteDialog = ref(false)
const isDeleting = ref(false)
const canDelete = computed(() => {
if (!policy.value?.destroy) return false
if (currentUser.value?.id === userId.value) return false
return true
})
async function handleDelete() {
if (isNil(user.value)) return
isDeleting.value = true
try {
await usersApi.delete(user.value.id)
snack.success("User deleted.")
await router.push({ name: "administration/UsersPage" })
} catch (error) {
snack.error(`Failed to delete user: ${error}`)
} finally {
isDeleting.value = false
}
}
async function saveWrapper() {
if (isNil(user.value)) return
if (headerActionsFormCard.value === null) return
const { valid } = await headerActionsFormCard.value.validate()
if (!valid) return
try {
await save()
snack.success("User saved!")
emit("saved", user.value.id)
} catch (error) {
snack.error(`Failed to save user: ${error}`)
}
}
</script>