Files
huly-platform/plugins/hr-resources/src/components/CreateRequest.svelte
T
2024-05-13 22:31:55 +07:00

181 lines
5.2 KiB
Svelte

<!--
// Copyright © 2022 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
import calendar from '@hcengineering/calendar'
import { Employee } from '@hcengineering/contact'
import { EmployeeBox } from '@hcengineering/contact-resources'
import core, { DocumentQuery, generateId, Markup, Ref } from '@hcengineering/core'
import { Request, RequestType, Staff, timeToTzDate } from '@hcengineering/hr'
import { translate } from '@hcengineering/platform'
import { Card, createQuery, getClient } from '@hcengineering/presentation'
import { EmptyMarkup } from '@hcengineering/text-editor'
import ui, {
Button,
DateRangePresenter,
DropdownLabelsIntl,
IconAttachment,
Label,
themeStore
} from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import hr from '../plugin'
import { getRequests } from '../utils'
export let staff: Staff
export let date: Date
export let readonly: boolean
export let docQuery: DocumentQuery<Employee> | undefined
export let employeeRequests: Map<Ref<Staff>, Request[]>
let description: Markup = EmptyMarkup
let employee: Ref<Employee> = staff._id
const objectId: Ref<Request> = generateId()
let descriptionBox: AttachmentStyledBox
const dispatch = createEventDispatcher()
const client = getClient()
const typesQuery = createQuery()
let types: RequestType[] = []
let type: RequestType | undefined = undefined
let typeLabel = ''
$: type && translate(type.label, {}, $themeStore.language).then((p) => (typeLabel = p))
typesQuery.query(hr.class.RequestType, {}, (res) => {
types = res
if (type === undefined) {
type = types[0]
}
})
let value = new Date(date).getTime()
$: dueDate = new Date(value).getTime()
export function canClose (): boolean {
return description.length === 0
}
async function saveRequest () {
let date: number | undefined
if (value != null) date = value
if (date === undefined) return
if (type === undefined) return
if (employee === null) return
await client.addCollection(hr.class.Request, hr.space.HR, employee, staff._class, 'requests', {
type: type._id,
tzDate: timeToTzDate(date),
tzDueDate: timeToTzDate(dueDate),
description,
department: staff.department
})
await descriptionBox.createAttachments()
}
function typeSelected (_id: Ref<RequestType>): void {
type = types.find((p) => p._id === _id)
}
function moreThanLimit (
employeeRequests: Map<Ref<Staff>, Request[]>,
staff: Staff,
startDate: Date,
endDate: Date,
type: RequestType | undefined
): boolean {
if (employeeRequests === undefined) return true
if (type === undefined) return true
const requests = getRequests(employeeRequests, startDate, endDate, staff._id)
return requests.length > 0
}
$: notLimit = moreThanLimit(
employeeRequests,
staff,
new Date(value),
new Date(new Date(dueDate).setHours(23, 59, 59, 999)),
type
)
</script>
<Card
label={hr.string.CreateRequest}
labelProps={{ type: typeLabel }}
okAction={saveRequest}
canSave={value !== undefined && !notLimit}
gap={'gapV-4'}
on:close={() => {
dispatch('close')
}}
on:changeContent
>
<svelte:fragment slot="header">
<EmployeeBox
label={hr.string.SelectEmployee}
placeholder={hr.string.SelectEmployee}
kind={'regular'}
size={'large'}
bind:value={employee}
{readonly}
showNavigate={false}
{docQuery}
/>
</svelte:fragment>
<DropdownLabelsIntl
items={types.map((p) => {
return { id: p._id, label: p.label }
})}
label={hr.string.RequestType}
on:selected={(e) => {
typeSelected(e.detail)
}}
/>
<AttachmentStyledBox
bind:this={descriptionBox}
{objectId}
_class={hr.class.Request}
space={hr.space.HR}
alwaysEdit
showButtons={false}
maxHeight={'card'}
bind:content={description}
placeholder={core.string.Description}
/>
<svelte:fragment slot="pool">
<DateRangePresenter bind:value editable labelNull={ui.string.SelectDate} kind={'regular'} size={'large'} />
<DateRangePresenter
bind:value={dueDate}
labelNull={calendar.string.DueTo}
editable
kind={'regular'}
size={'large'}
/>
</svelte:fragment>
<svelte:fragment slot="footer">
<Button
icon={IconAttachment}
size={'large'}
on:click={() => {
descriptionBox.handleAttach()
}}
/>
</svelte:fragment>
<svelte:fragment slot="error">
{#if notLimit}
<Label label={hr.string.ExistingRequests} />
{/if}
</svelte:fragment>
</Card>