update
This commit is contained in:
@@ -4,21 +4,23 @@
|
||||
{{ $t(title) }}
|
||||
</template>
|
||||
<template #footer>
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 q-mt-md q-mb-xs fix-disabled-btn"
|
||||
:disable="!isFormValid"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
<div class="w100 q-pa-md">
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 fix-disabled-btn"
|
||||
:disable="!isFormValid"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<pn-scroll-list>
|
||||
<div class="flex column items-center q-pa-md q-pb-sm">
|
||||
<slot name="myCompany"/>
|
||||
<pn-image-selector
|
||||
v-model="modelValue.logo"
|
||||
v-model="companyMod.logo"
|
||||
:size="100"
|
||||
:iconsize="80"
|
||||
class="q-pb-lg"
|
||||
@@ -27,7 +29,7 @@
|
||||
<q-input
|
||||
v-for="input in textInputs"
|
||||
:key="input.id"
|
||||
v-model.trim="modelValue[input.val]"
|
||||
v-model.trim="companyMod[input.val]"
|
||||
dense
|
||||
filled
|
||||
class="w100"
|
||||
@@ -38,7 +40,7 @@
|
||||
? 'input-fix q-pt-sm'
|
||||
: 'q-pt-sm'"
|
||||
:label="input.label ? $t(input.label) : void 0"
|
||||
:rules="input.val === 'name' ? [rules[input.val]] : []"
|
||||
:rules="input.rules"
|
||||
no-error-icon
|
||||
:label-slot="Boolean(input.label)"
|
||||
>
|
||||
@@ -57,24 +59,35 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, reactive } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { CompanyParams } from 'types/Company'
|
||||
import { convertEmptyStringsToNull } from 'src/utils/helpers'
|
||||
import { removeNullKeys } from 'utils/helpers'
|
||||
|
||||
const { t }= useI18n()
|
||||
|
||||
const modelValue = defineModel<CompanyParams>({
|
||||
required: true
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
title: string,
|
||||
btnText: string
|
||||
btnText: string,
|
||||
company?: CompanyParams
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update'])
|
||||
|
||||
type CompType = {
|
||||
[K in keyof CompanyParams]: CompanyParams[K] extends number ? never : CompanyParams[K]
|
||||
}
|
||||
|
||||
const companyMod = reactive<CompType>({
|
||||
name: props.company?.name ?? '',
|
||||
description: props.company?.description ?? '',
|
||||
site: props.company?.site ?? '',
|
||||
address: props.company?.address ?? '',
|
||||
phone: props.company?.phone ?? '',
|
||||
email: props.company?.email ?? '',
|
||||
logo: props.company?.logo ?? null
|
||||
})
|
||||
|
||||
interface TextInput {
|
||||
id: number
|
||||
label?: string
|
||||
@@ -83,34 +96,42 @@
|
||||
rules: ((value: string) => boolean | string)[]
|
||||
}
|
||||
|
||||
const rules = {
|
||||
name: (val: string) => !!val?.trim() || rulesErrorMessage['name']
|
||||
}
|
||||
|
||||
const textInputs: TextInput[] = [
|
||||
{ id: 1, val: 'name', label: 'company_block__name', rules: [] },
|
||||
{ id: 1, val: 'name', label: 'company_block__name', rules: [rules.name] },
|
||||
{ id: 2, val: 'description', label: 'company_block__description', rules: [] },
|
||||
{ id: 3, val: 'site', icon: 'mdi-web', rules: [] },
|
||||
{ id: 4, val: 'address', icon: 'mdi-map-marker-outline', rules: [] },
|
||||
{ id: 5, val: 'phone', icon: 'mdi-phone-outline', rules: [] },
|
||||
{ id: 6, val: 'email', icon: 'mdi-email-outline', rules: [] }
|
||||
]
|
||||
] as const
|
||||
|
||||
const rulesErrorMessage = {
|
||||
name: t('company_block__error_name')
|
||||
}
|
||||
|
||||
const rules = {
|
||||
name: (val: CompanyParams['name']) => !!val?.trim() || rulesErrorMessage['name']
|
||||
}
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
const validations = {
|
||||
name: rules.name(modelValue.value.name) === true
|
||||
name: companyMod.name && rules.name(companyMod.name) === true
|
||||
}
|
||||
|
||||
return Object.values(validations).every(Boolean)
|
||||
})
|
||||
|
||||
function onSubmit() {
|
||||
const cleanedData = convertEmptyStringsToNull(modelValue.value)
|
||||
emit('update', cleanedData)
|
||||
const outData = {
|
||||
name: companyMod.name,
|
||||
description: companyMod.description ?? (typeof props.company?.description === 'string' ? '' : null),
|
||||
site: companyMod.site ?? (typeof props.company?.site === 'string' ? '' : null),
|
||||
address: companyMod.address ?? (typeof props.company?.address === 'string' ? '' : null),
|
||||
phone: companyMod.phone ?? (typeof props.company?.phone === 'string' ? '' : null),
|
||||
email: companyMod.email ?? (typeof props.company?.email === 'string' ? '' : null),
|
||||
logo: companyMod.logo
|
||||
}
|
||||
emit('update', removeNullKeys(outData))
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
:style="{
|
||||
height: sizePx,
|
||||
maxWidth: sizePx,
|
||||
borderRadius: avatar ? String(size/2) + 'px' : 'var(--top-raduis)',
|
||||
borderRadius: avatar ? String(size/2) + 'px' : 'var(--top-radius)',
|
||||
}"
|
||||
@click="showDialog = true"
|
||||
/>
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
<q-card
|
||||
class="fix-card-width flex column no-scroll no-wrap q-px-none"
|
||||
style="
|
||||
border-top-left-radius: var(--top-raduis) !important;
|
||||
border-top-right-radius: var(--top-raduis) !important;
|
||||
border-top-left-radius: var(--top-radius) !important;
|
||||
border-top-right-radius: var(--top-radius) !important;
|
||||
"
|
||||
>
|
||||
<div
|
||||
@@ -46,7 +46,12 @@
|
||||
>
|
||||
<div>
|
||||
<div class="flex column q-mx-xs">
|
||||
<span class="text-h6 ellipsis">{{ $t(title) }}</span>
|
||||
<span
|
||||
class="text-h6"
|
||||
style="line-height: 1.5rem;"
|
||||
>
|
||||
{{ $t(title) }}
|
||||
</span>
|
||||
<span v-if="caption" class="text-grey text-caption">{{ $t(caption) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,20 +18,20 @@
|
||||
<div class="flex column justify-center col-grow items-center">
|
||||
<q-icon :name="icon" size="160px" class="q-pb-md"/>
|
||||
<div class="text-h6 text-brand">
|
||||
{{message1}}
|
||||
{{ message1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="message2" class="text-caption" align="center">
|
||||
{{message2}}
|
||||
<div v-if="message2" class="text-caption text-center">
|
||||
{{ message2 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
defineProps<{
|
||||
icon: string
|
||||
message1: string
|
||||
message2?: string
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<slot name="title"/>
|
||||
</div>
|
||||
<slot/>
|
||||
<div class="bg-white w100 q-ma-none q-px-md flex items-center">
|
||||
<div class="bg-white w100">
|
||||
<slot name="footer"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
>
|
||||
<div
|
||||
id="card-body-header"
|
||||
style="flex-shrink: 0; min-height: var(--top-raduis);"
|
||||
v-if="slots['card-body-header']"
|
||||
style="flex-shrink: 0; min-height: var(--top-radius);"
|
||||
>
|
||||
<q-resize-observer @resize="onHeaderResize"/>
|
||||
<slot name="card-body-header"/>
|
||||
</div>
|
||||
<div id="card-body" >
|
||||
<div id="card-body"
|
||||
class="top-rounded-card bg-white"
|
||||
style="padding-top: var(--top-radius);"
|
||||
>
|
||||
<q-resize-observer @resize="onBodyResize"/>
|
||||
<pn-shadow-scroll :hideShadows="isResizing" :height="scrollAreaHeight">
|
||||
<slot/>
|
||||
@@ -21,6 +25,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import { useSlots } from 'vue'
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
const heightCard = ref(100)
|
||||
const scrollAreaHeight = ref(100)
|
||||
@@ -37,7 +44,7 @@ async function onHeaderResize(size: sizeParams) {
|
||||
}
|
||||
|
||||
async function onBodyResize(size: sizeParams) {
|
||||
heightCard.value = size.height
|
||||
heightCard.value = size.height - parseInt(String(getComputedStyle(document.documentElement).getPropertyValue('--top-radius'))) // subtract padding var(top-radius)
|
||||
await updateScrollAreaHeight()
|
||||
}
|
||||
|
||||
@@ -70,11 +77,6 @@ watch(heightCard, () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.glass-card {
|
||||
opacity: 1 !important;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#page-card {
|
||||
flex: 1 0 auto;
|
||||
min-height: 0;
|
||||
|
||||
@@ -4,27 +4,30 @@
|
||||
{{ $t(title) }}
|
||||
</template>
|
||||
<template #footer>
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 q-mt-md q-mb-xs fix-disabled-btn"
|
||||
:disable="!isFormValid"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
<div class="w100 q-pa-md">
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 fix-disabled-btn"
|
||||
:disable="!isFormValid"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<pn-scroll-list>
|
||||
<div class="flex column items-center q-pa-md q-pb-sm">
|
||||
<pn-image-selector
|
||||
v-model="modelValue.logo"
|
||||
v-model="projectMod.logo"
|
||||
:size="100"
|
||||
:iconsize="80"
|
||||
:iconsize="80"
|
||||
type="rounded"
|
||||
class="q-pb-lg"
|
||||
/>
|
||||
<div class="q-gutter-y-lg w100">
|
||||
<q-input
|
||||
v-model="modelValue.name"
|
||||
v-model="projectMod.name"
|
||||
no-error-icon
|
||||
dense
|
||||
filled
|
||||
@@ -38,7 +41,7 @@
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="modelValue.description"
|
||||
v-model="projectMod.description"
|
||||
dense
|
||||
filled
|
||||
autogrow
|
||||
@@ -53,44 +56,52 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, reactive } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { ProjectParams } from 'types/Project'
|
||||
import { convertEmptyStringsToNull } from 'src/utils/helpers'
|
||||
import { removeNullKeys } from 'utils/helpers'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const modelValue = defineModel<ProjectParams>({
|
||||
required: true
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
title: string,
|
||||
btnText: string
|
||||
btnText: string,
|
||||
project?: ProjectParams
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update'])
|
||||
|
||||
const projectMod = reactive({
|
||||
name: props.project?.name ?? '',
|
||||
description: props.project?.description ?? '',
|
||||
logo: props.project?.logo ?? null
|
||||
})
|
||||
|
||||
const rulesErrorMessage = {
|
||||
name: t('project_block__error_name')
|
||||
}
|
||||
|
||||
const rules = {
|
||||
name: (val: ProjectParams['name']) => !!val?.trim() || rulesErrorMessage['name']
|
||||
name: (val: string) => !!val?.trim() || rulesErrorMessage['name']
|
||||
}
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
const validations = {
|
||||
name: rules.name(modelValue.value.name) === true
|
||||
name: projectMod.name && rules.name(projectMod.name) === true
|
||||
}
|
||||
|
||||
return Object.values(validations).every(Boolean)
|
||||
})
|
||||
|
||||
function onSubmit() {
|
||||
const cleanedData = convertEmptyStringsToNull(modelValue.value)
|
||||
emit('update', cleanedData)
|
||||
const outData = {
|
||||
name: projectMod.name,
|
||||
description: projectMod.description ?? (typeof props.project?.description === 'string' ? '' : null),
|
||||
logo: projectMod.logo
|
||||
}
|
||||
emit('update', removeNullKeys(outData))
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -4,43 +4,45 @@
|
||||
{{ $t(title) }}
|
||||
</template>
|
||||
<template #footer>
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 q-mt-md q-mb-xs fix-disabled-btn"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
<div class="w100 q-pa-md">
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 fix-disabled-btn"
|
||||
@click = "onSubmit"
|
||||
>
|
||||
{{ $t(btnText) }}
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<pn-scroll-list>
|
||||
<div class="flex column items-center q-pa-md q-pb-sm">
|
||||
<div class="relative-position">
|
||||
<pn-auto-avatar
|
||||
:img="modelValue.photo"
|
||||
:img="userMod.photo"
|
||||
:name="tname"
|
||||
size="100px"
|
||||
class="q-pb-lg"
|
||||
:style="!userStatus ? {} : { filter: 'grayscale(100%)'}"
|
||||
/>
|
||||
<div
|
||||
v-if="userStatus"
|
||||
class="absolute-center text-h4 text-bold q-pa-sm text-center"
|
||||
:class ="'status-' + userStatus.status"
|
||||
>
|
||||
{{ $t(userStatus.text) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="userStatus"
|
||||
class="absolute-center text-h4 text-bold q-pa-sm text-center"
|
||||
:class ="'status-' + userStatus.status"
|
||||
>
|
||||
{{ $t(userStatus.text) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex row items-start justify-center no-wrap q-pb-lg">
|
||||
<div class="flex column justify-center">
|
||||
<div class="text-bold q-pr-xs text-center" align="center">{{ tname }}</div>
|
||||
<div caption class="text-blue text-caption" align="center" v-if="modelValue.username">{{ modelValue.username }}</div>
|
||||
<div caption class="text-blue text-caption" align="center" v-if="user?.username">{{ user.username }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="q-gutter-y-lg w100">
|
||||
<q-input
|
||||
v-model.trim="modelValue.fullname"
|
||||
v-model.trim="userMod.fullname"
|
||||
dense
|
||||
filled
|
||||
class = "w100"
|
||||
@@ -48,7 +50,7 @@
|
||||
/>
|
||||
|
||||
<q-select
|
||||
v-model="modelValue.company_id"
|
||||
v-model="userMod.company_id"
|
||||
:options="displayCompanies"
|
||||
dense
|
||||
filled
|
||||
@@ -84,7 +86,7 @@
|
||||
</q-select>
|
||||
|
||||
<q-input
|
||||
v-model.trim="modelValue.department"
|
||||
v-model.trim="userMod.department"
|
||||
dense
|
||||
filled
|
||||
class = "w100 q-pt-sm"
|
||||
@@ -92,7 +94,7 @@
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model.trim="modelValue.role"
|
||||
v-model.trim="userMod.role"
|
||||
dense
|
||||
filled
|
||||
class = "w100 q-pt-sm"
|
||||
@@ -100,7 +102,7 @@
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model.trim="modelValue.phone"
|
||||
v-model.trim="userMod.phone"
|
||||
dense
|
||||
filled
|
||||
class = "w100 q-pt-sm"
|
||||
@@ -111,7 +113,7 @@
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model.trim="modelValue.email"
|
||||
v-model.trim="userMod.email"
|
||||
dense
|
||||
filled
|
||||
class = "w100 q-pt-sm"
|
||||
@@ -129,30 +131,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, reactive } from 'vue'
|
||||
import { useCompaniesStore } from 'stores/companies'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { convertEmptyStringsToNull } from 'src/utils/helpers'
|
||||
import { removeNullKeys } from 'utils/helpers'
|
||||
import type { User } from 'types/User'
|
||||
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const modelValue = defineModel<User>({
|
||||
required: true
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
title: string,
|
||||
btnText: string
|
||||
btnText: string,
|
||||
user?: User
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update'])
|
||||
|
||||
function onSubmit() {
|
||||
const cleanedData = convertEmptyStringsToNull(modelValue.value)
|
||||
emit('update', cleanedData)
|
||||
}
|
||||
const userMod = reactive({
|
||||
fullname: props.user?.fullname ?? '',
|
||||
company_id: props.user?.company_id ?? null,
|
||||
department: props.user?.department ?? '',
|
||||
role: props.user?.role ?? '',
|
||||
phone: props.user?.phone ?? '',
|
||||
email: props.user?.email ?? '',
|
||||
photo: props.user?.photo ?? null
|
||||
})
|
||||
|
||||
const companiesStore = useCompaniesStore()
|
||||
const companies = computed(() => companiesStore.companies)
|
||||
@@ -171,18 +174,31 @@
|
||||
])
|
||||
|
||||
const tname = computed(() =>
|
||||
[modelValue.value?.firstname, modelValue.value?.lastname]
|
||||
[props.user?.firstname, props.user?.lastname]
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
)
|
||||
|
||||
const userStatus = computed(() => {
|
||||
if (modelValue.value.is_blocked) return { status: 'blocked', text: 'user_block__user_blocked' }
|
||||
if (modelValue.value.is_leave) return { status: 'leave', text: 'user_block__user_leave' }
|
||||
if (!modelValue.value.is_terms_accepted) return { status: 'pending', text: 'user_block__user_pending' }
|
||||
if (props.user?.is_blocked) return { status: 'blocked', text: 'user_block__user_blocked' }
|
||||
if (props.user?.is_leave) return { status: 'leave', text: 'user_block__user_leave' }
|
||||
if (!props.user?.is_terms_accepted) return { status: 'pending', text: 'user_block__user_pending' }
|
||||
return null
|
||||
})
|
||||
|
||||
function onSubmit() {
|
||||
const outData = {
|
||||
fullname: userMod.fullname ?? (typeof props.user?.fullname === 'string' ? '' : null),
|
||||
company_id: userMod.company_id,
|
||||
department: userMod.department ?? (typeof props.user?.department === 'string' ? '' : null),
|
||||
role: userMod.role ?? (typeof props.user?.role === 'string' ? '' : null),
|
||||
phone: userMod.phone ?? (typeof props.user?.phone === 'string' ? '' : null),
|
||||
email: userMod.email ?? (typeof props.user?.email === 'string' ? '' : null),
|
||||
photo: userMod.photo
|
||||
}
|
||||
emit('update', removeNullKeys(outData))
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user