From 854eabcbdc583f2b1e2962e7ce0df03c24d3b8db Mon Sep 17 00:00:00 2001 From: lme-axelor <102581501+lme-axelor@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:11:20 +0100 Subject: [PATCH 01/26] chore: prepare version 8.3.0 --- android/app/build.gradle | 2 +- ios/AosMobile.xcodeproj/project.pbxproj | 8 ++++---- package.json | 24 ++++++++++++------------ packages/apps/crm/package.json | 6 +++--- packages/apps/helpdesk/package.json | 6 +++--- packages/apps/hr/package.json | 6 +++--- packages/apps/intervention/package.json | 8 ++++---- packages/apps/manufacturing/package.json | 8 ++++---- packages/apps/project/package.json | 8 ++++---- packages/apps/quality/package.json | 6 +++--- packages/apps/sale/package.json | 8 ++++---- packages/apps/stock/package.json | 6 +++--- packages/core/package.json | 6 +++--- packages/error/package.json | 2 +- packages/ui/package.json | 2 +- 15 files changed, 53 insertions(+), 53 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 545c3330be..c3cf4adff1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -80,7 +80,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 38 - versionName "8.2.4" + versionName "8.3.0" } signingConfigs { debug { diff --git a/ios/AosMobile.xcodeproj/project.pbxproj b/ios/AosMobile.xcodeproj/project.pbxproj index 4d6c481cf7..8a6a557481 100644 --- a/ios/AosMobile.xcodeproj/project.pbxproj +++ b/ios/AosMobile.xcodeproj/project.pbxproj @@ -478,7 +478,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 8.2.4; + MARKETING_VERSION = 8.3.0; OTHER_LDFLAGS = ( "-ObjC", "-lc++", @@ -505,7 +505,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 8.2.4; + MARKETING_VERSION = 8.3.0; OTHER_LDFLAGS = ( "-ObjC", "-lc++", @@ -532,7 +532,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 8.2.4; + MARKETING_VERSION = 8.3.0; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 8.2.4; + MARKETING_VERSION = 8.3.0; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", diff --git a/package.json b/package.json index 60d3b8de04..fc254e08da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aos-mobile", - "version": "8.2.4", + "version": "8.3.0", "private": true, "workspaces": { "packages": [ @@ -30,17 +30,17 @@ "postinstall": "patch-package" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-crm": "8.2.4", - "@axelor/aos-mobile-helpdesk": "8.2.4", - "@axelor/aos-mobile-hr": "8.2.4", - "@axelor/aos-mobile-intervention": "8.2.4", - "@axelor/aos-mobile-manufacturing": "8.2.4", - "@axelor/aos-mobile-project": "8.2.4", - "@axelor/aos-mobile-quality": "8.2.4", - "@axelor/aos-mobile-sale": "8.2.4", - "@axelor/aos-mobile-stock": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-crm": "8.3.0", + "@axelor/aos-mobile-helpdesk": "8.3.0", + "@axelor/aos-mobile-hr": "8.3.0", + "@axelor/aos-mobile-intervention": "8.3.0", + "@axelor/aos-mobile-manufacturing": "8.3.0", + "@axelor/aos-mobile-project": "8.3.0", + "@axelor/aos-mobile-quality": "8.3.0", + "@axelor/aos-mobile-sale": "8.3.0", + "@axelor/aos-mobile-stock": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@react-native-clipboard/clipboard": "1.14.1", "@react-native-community/slider": "^4.5.4", "bootstrap-icons": "^1.10.3", diff --git a/packages/apps/crm/package.json b/packages/apps/crm/package.json index d03bae5cb4..c72fbb6528 100644 --- a/packages/apps/crm/package.json +++ b/packages/apps/crm/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-crm", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,8 +27,8 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/helpdesk/package.json b/packages/apps/helpdesk/package.json index e77bf951b6..a62c93a520 100644 --- a/packages/apps/helpdesk/package.json +++ b/packages/apps/helpdesk/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-helpdesk", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,8 +27,8 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/hr/package.json b/packages/apps/hr/package.json index 8c52d1b51d..a16bd98190 100644 --- a/packages/apps/hr/package.json +++ b/packages/apps/hr/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-hr", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,8 +27,8 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/intervention/package.json b/packages/apps/intervention/package.json index f580253517..5507727fa3 100644 --- a/packages/apps/intervention/package.json +++ b/packages/apps/intervention/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-intervention", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,9 +27,9 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-crm": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-crm": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/manufacturing/package.json b/packages/apps/manufacturing/package.json index 5774830d9c..76b0a0f800 100644 --- a/packages/apps/manufacturing/package.json +++ b/packages/apps/manufacturing/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-manufacturing", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,9 +27,9 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-stock": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-stock": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/project/package.json b/packages/apps/project/package.json index cac19e938e..243e5e4b60 100644 --- a/packages/apps/project/package.json +++ b/packages/apps/project/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-project", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,9 +27,9 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-hr": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-hr": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/quality/package.json b/packages/apps/quality/package.json index fa31d72c2e..36873f59e7 100644 --- a/packages/apps/quality/package.json +++ b/packages/apps/quality/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-quality", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,8 +27,8 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/sale/package.json b/packages/apps/sale/package.json index 9ecdf3886b..e4379e77d8 100644 --- a/packages/apps/sale/package.json +++ b/packages/apps/sale/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-sale", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,9 +27,9 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-core": "8.2.4", - "@axelor/aos-mobile-crm": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-core": "8.3.0", + "@axelor/aos-mobile-crm": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/apps/stock/package.json b/packages/apps/stock/package.json index 8daae4ecc1..43bebf8d16 100644 --- a/packages/apps/stock/package.json +++ b/packages/apps/stock/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-stock", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -27,8 +27,8 @@ "react-native": "0.73.9" }, "dependencies": { - "@axelor/aos-mobile-ui": "8.2.4", - "@axelor/aos-mobile-core": "8.2.4", + "@axelor/aos-mobile-ui": "8.3.0", + "@axelor/aos-mobile-core": "8.3.0", "@reduxjs/toolkit": "^2.2.7" }, "devDependencies": { diff --git a/packages/core/package.json b/packages/core/package.json index c39c4809e7..91eb2f217a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-core", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { @@ -24,8 +24,8 @@ "license:add": "npx add-copyright-header --generate --dir 'src'" }, "dependencies": { - "@axelor/aos-mobile-error": "8.2.4", - "@axelor/aos-mobile-ui": "8.2.4", + "@axelor/aos-mobile-error": "8.3.0", + "@axelor/aos-mobile-ui": "8.3.0", "@react-navigation/drawer": "6.7.2", "@react-navigation/native": "6.1.18", "@react-navigation/native-stack": "6.11.0", diff --git a/packages/error/package.json b/packages/error/package.json index 53f2042d62..bc10d829e2 100644 --- a/packages/error/package.json +++ b/packages/error/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-error", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { diff --git a/packages/ui/package.json b/packages/ui/package.json index 63fe851359..64f7f889c2 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@axelor/aos-mobile-ui", - "version": "8.2.4", + "version": "8.3.0", "author": "Axelor", "license": "AGPL-3.0-only", "publishConfig": { From d7f376799a94108b9c0262e4a42bea0f90af82a3 Mon Sep 17 00:00:00 2001 From: vhu-axelor <146069039+vhu-axelor@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:02:11 +0200 Subject: [PATCH 02/26] feat: add leave list view (#679) * RM#82777 --- packages/apps/hr/src/api/index.ts | 4 + packages/apps/hr/src/api/leave-api.js | 91 +++++++++++++ .../components/atoms/LeaveCard/LeaveCard.tsx | 121 +++++++++++++++++ .../apps/hr/src/components/atoms/index.js | 1 + .../LeaveActionCard/LeaveActionCard.tsx | 78 +++++++++++ .../apps/hr/src/components/molecules/index.js | 1 + .../templates/LeaveFilters/LeaveFilters.tsx | 117 +++++++++++++++++ .../LeaveWaitingValidationSearchBar.tsx | 74 +++++++++++ .../apps/hr/src/components/templates/index.js | 2 + .../hr/src/features/asyncFunctions-index.ts | 1 + packages/apps/hr/src/features/index.js | 1 + packages/apps/hr/src/features/leaveSlice.js | 95 ++++++++++++++ packages/apps/hr/src/i18n/en.json | 7 +- packages/apps/hr/src/i18n/fr.json | 7 +- packages/apps/hr/src/index.ts | 12 ++ packages/apps/hr/src/models/objectFields.ts | 14 ++ packages/apps/hr/src/models/searchFields.ts | 1 + packages/apps/hr/src/models/sortFields.ts | 1 + packages/apps/hr/src/models/typeObjects.ts | 58 ++++++++ .../screens/leaveRequests/LeaveListScreen.tsx | 124 ++++++++++++++++++ .../hr/src/screens/leaveRequests/index.ts | 32 +++++ packages/apps/hr/src/types/index.ts | 1 + packages/apps/hr/src/types/leave.ts | 26 ++++ 23 files changed, 867 insertions(+), 2 deletions(-) create mode 100644 packages/apps/hr/src/api/leave-api.js create mode 100644 packages/apps/hr/src/components/atoms/LeaveCard/LeaveCard.tsx create mode 100644 packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx create mode 100644 packages/apps/hr/src/components/templates/LeaveFilters/LeaveFilters.tsx create mode 100644 packages/apps/hr/src/components/templates/LeaveWaitingValidationSearchBar/LeaveWaitingValidationSearchBar.tsx create mode 100644 packages/apps/hr/src/features/leaveSlice.js create mode 100644 packages/apps/hr/src/screens/leaveRequests/LeaveListScreen.tsx create mode 100644 packages/apps/hr/src/screens/leaveRequests/index.ts create mode 100644 packages/apps/hr/src/types/leave.ts diff --git a/packages/apps/hr/src/api/index.ts b/packages/apps/hr/src/api/index.ts index e62ace7d44..a44e4e55fc 100644 --- a/packages/apps/hr/src/api/index.ts +++ b/packages/apps/hr/src/api/index.ts @@ -43,6 +43,10 @@ export { } from './expense-line-api'; export {searchExpenseType as searchExpenseTypeApi} from './expense-type-api'; export {searchKilometricAllowParam as searchKilometricAllowParamApi} from './kilometric-allow-param-api'; +export { + fetchLeave as fetchLeaveApi, + fetchLeaveToValidate as fetchLeaveToValidateApi, +} from './leave-api'; export { searchManufOrder as searchManufOrderApi, searchOperationOrder as searchOperationOrderApi, diff --git a/packages/apps/hr/src/api/leave-api.js b/packages/apps/hr/src/api/leave-api.js new file mode 100644 index 0000000000..9f2c1cf94f --- /dev/null +++ b/packages/apps/hr/src/api/leave-api.js @@ -0,0 +1,91 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { + createStandardSearch, + getTypes, + getSearchCriterias, +} from '@axelor/aos-mobile-core'; + +const createLeaveCriteria = (userId, selectedStatus) => { + const criteria = [ + { + fieldName: 'employee.user.id', + operator: '=', + value: userId, + }, + { + fieldName: 'toJustifyLeaveReason', + operator: '=', + value: false, + }, + ]; + + if (selectedStatus != null) { + criteria.push({ + fieldName: 'statusSelect', + operator: '=', + value: selectedStatus, + }); + } + + return criteria; +}; + +const createLeaveToValidateCriteria = (searchValue, user) => { + const LeaveRequest = getTypes().LeaveRequest; + + const criteria = [ + getSearchCriterias('hr_leave', searchValue), + { + fieldName: 'statusSelect', + operator: '=', + value: LeaveRequest?.statusSelect.WaitingValidation, + }, + ]; + + if (!user?.employee?.hrManager) { + criteria.push({ + fieldName: 'employee.managerUser.id', + operator: '=', + value: user?.id, + }); + } + + return criteria; +}; + +export async function fetchLeave({userId, selectedStatus, page = 0}) { + return createStandardSearch({ + model: 'com.axelor.apps.hr.db.LeaveRequest', + criteria: createLeaveCriteria(userId, selectedStatus), + fieldKey: 'hr_leave', + sortKey: 'hr_leave', + page, + }); +} + +export async function fetchLeaveToValidate({searchValue, user, page = 0}) { + return createStandardSearch({ + model: 'com.axelor.apps.hr.db.LeaveRequest', + criteria: createLeaveToValidateCriteria(searchValue, user), + fieldKey: 'hr_leave', + sortKey: 'hr_leave', + page, + }); +} diff --git a/packages/apps/hr/src/components/atoms/LeaveCard/LeaveCard.tsx b/packages/apps/hr/src/components/atoms/LeaveCard/LeaveCard.tsx new file mode 100644 index 0000000000..7463a2ba7e --- /dev/null +++ b/packages/apps/hr/src/components/atoms/LeaveCard/LeaveCard.tsx @@ -0,0 +1,121 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useMemo} from 'react'; +import {StyleSheet} from 'react-native'; +import {PeriodDisplay, useTypeHelpers, useTypes} from '@axelor/aos-mobile-core'; +import {ObjectCard, TextUnit} from '@axelor/aos-mobile-ui'; +import {Leave} from '../../../types'; + +interface LeaveCardProps { + style?: any; + mode: number; + statusSelect: number; + startDate: string; + endDate: string; + duration: number; + durationUnitSelect: number; + reason: string; + company: string; + employee: string; + onPress: () => void; +} + +const LeaveCard = ({ + style, + mode, + statusSelect, + startDate, + endDate, + duration, + durationUnitSelect, + reason, + company, + employee, + onPress, +}: LeaveCardProps) => { + const {LeaveReason, LeaveRequest} = useTypes(); + const {getItemColor, getItemTitle} = useTypeHelpers(); + + const styles = useMemo( + () => + getStyles( + getItemColor(LeaveRequest?.statusSelect, statusSelect)?.background, + ), + [LeaveRequest?.statusSelect, getItemColor, statusSelect], + ); + + return ( + + ), + }, + { + iconName: 'tag-fill', + indicatorText: reason, + }, + { + iconName: 'building-fill', + indicatorText: company, + }, + { + iconName: 'person-fill', + indicatorText: employee, + hideIf: mode === Leave.mode.myLeaves, + }, + ], + }} + sideBadges={{ + items: [ + { + customComponent: ( + + ), + }, + ], + }} + /> + ); +}; + +const getStyles = color => + StyleSheet.create({ + container: { + flex: 1, + borderLeftWidth: 7, + borderLeftColor: color, + paddingRight: 10, + marginHorizontal: 1, + marginVertical: 2, + }, + textUnit: { + alignSelf: 'flex-end', + }, + }); + +export default LeaveCard; diff --git a/packages/apps/hr/src/components/atoms/index.js b/packages/apps/hr/src/components/atoms/index.js index 15c4220267..77f4d7f4d6 100644 --- a/packages/apps/hr/src/components/atoms/index.js +++ b/packages/apps/hr/src/components/atoms/index.js @@ -18,5 +18,6 @@ export {default as ExpenseCard} from './ExpenseCard/ExpenseCard'; export {default as ExpenseLineCard} from './ExpenseLineCard/ExpenseLineCard'; +export {default as LeaveCard} from './LeaveCard/LeaveCard'; export {default as TimeCard} from './TimeCard/TimeCard'; export {default as TimesheetCard} from './TimesheetCard/TimesheetCard'; diff --git a/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx b/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx new file mode 100644 index 0000000000..ed9cd1e418 --- /dev/null +++ b/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx @@ -0,0 +1,78 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React from 'react'; +import {useTranslator, useTypes} from '@axelor/aos-mobile-core'; +import {ActionCard} from '@axelor/aos-mobile-ui'; +import {LeaveCard} from '../../atoms'; +import {Leave} from '../../../types'; + +interface LeaveActionCardProps { + mode: number; + leave: any; + onPress: () => void; + onSend: () => void; + onValidate: () => void; +} + +const LeaveActionCard = ({ + mode, + leave, + onPress, + onSend, + onValidate, +}: LeaveActionCardProps) => { + const I18n = useTranslator(); + const {LeaveRequest} = useTypes(); + + return ( + + + + ); +}; + +export default LeaveActionCard; diff --git a/packages/apps/hr/src/components/molecules/index.js b/packages/apps/hr/src/components/molecules/index.js index db48034a54..3425e88f09 100644 --- a/packages/apps/hr/src/components/molecules/index.js +++ b/packages/apps/hr/src/components/molecules/index.js @@ -20,6 +20,7 @@ export {default as ExpenseAddPopup} from './ExpenseAddPopup/ExpenseAddPopup'; export {default as ExpenseDetailsValidationButton} from './ExpenseDetailsValidationButton/ExpenseDetailsValidationButton'; export {default as ExpenseLineDetailCard} from './ExpenseLineDetailCard/ExpenseLineDetailCard'; export {default as ExpenseLineValidationButton} from './ExpenseLineValidationButton/ExpenseLineValidationButton'; +export {default as LeaveActionCard} from './LeaveActionCard/LeaveActionCard'; export {default as RefusalPopup} from './RefusalPopup/RefusalPopup'; export {default as TimeDetailCard} from './TimeDetailCard/TimeDetailCard'; export {default as TimerDeclareButton} from './TimerDeclareButton/TimerDeclareButton'; diff --git a/packages/apps/hr/src/components/templates/LeaveFilters/LeaveFilters.tsx b/packages/apps/hr/src/components/templates/LeaveFilters/LeaveFilters.tsx new file mode 100644 index 0000000000..7d139a9d0b --- /dev/null +++ b/packages/apps/hr/src/components/templates/LeaveFilters/LeaveFilters.tsx @@ -0,0 +1,117 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useEffect, useMemo} from 'react'; +import {StyleSheet, View} from 'react-native'; +import { + useDispatch, + useSelector, + useTranslator, + useTypes, + useTypeHelpers, +} from '@axelor/aos-mobile-core'; +import { + NumberBubble, + Picker, + ToggleSwitch, + useThemeColor, +} from '@axelor/aos-mobile-ui'; +import {fetchLeaveToValidate} from '../../../features/leaveSlice'; +import {Leave} from '../../../types'; +import {LeaveWaitingValidationSearchBar} from '../../templates'; + +interface LeaveFiltersProps { + mode: number; + onChangeMode: (mode: any) => void; + onChangeStatus: (status: any) => void; +} + +const LeaveFilters = ({ + mode, + onChangeMode, + onChangeStatus, +}: LeaveFiltersProps) => { + const Colors = useThemeColor(); + const I18n = useTranslator(); + const dispatch = useDispatch(); + const {LeaveRequest} = useTypes(); + const {getSelectionItems} = useTypeHelpers(); + + const {user} = useSelector(state => state.user); + const {managedEmployeeTotal} = useSelector(state => state.employee); + const {totalNumberLeaveToValidate} = useSelector(state => state.hr_leave); + + useEffect(() => { + dispatch((fetchLeaveToValidate as any)({user: user, page: 0})); + }, [dispatch, user]); + + const leaveStatusList = useMemo( + () => getSelectionItems(LeaveRequest?.statusSelect), + [getSelectionItems, LeaveRequest?.statusSelect], + ); + + return ( + + {(user?.employee?.hrManager || managedEmployeeTotal > 0) && ( + + } + onSwitch={() => { + onChangeStatus(null); + onChangeMode(_mode => + _mode === Leave.mode.myLeaves + ? Leave.mode.leavesToValidate + : Leave.mode.myLeaves, + ); + }} + /> + )} + {mode === Leave.mode.myLeaves ? ( + + ) : ( + + )} + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + }, + numberBubble: { + position: 'absolute', + right: '5%', + }, +}); + +export default LeaveFilters; diff --git a/packages/apps/hr/src/components/templates/LeaveWaitingValidationSearchBar/LeaveWaitingValidationSearchBar.tsx b/packages/apps/hr/src/components/templates/LeaveWaitingValidationSearchBar/LeaveWaitingValidationSearchBar.tsx new file mode 100644 index 0000000000..6361920cf0 --- /dev/null +++ b/packages/apps/hr/src/components/templates/LeaveWaitingValidationSearchBar/LeaveWaitingValidationSearchBar.tsx @@ -0,0 +1,74 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useCallback} from 'react'; +import { + displayItemName, + useDispatch, + useSelector, + useTranslator, +} from '@axelor/aos-mobile-core'; +import {AutoCompleteSearch} from '@axelor/aos-mobile-ui'; +import {fetchLeaveToValidate} from '../../../features/leaveSlice'; + +interface LeaveWaitingValidationSearchBarProps { + placeholderKey?: string; + defaultValue?: string; + onChange?: () => void; +} + +const LeaveWaitingValidationSearchBar = ({ + placeholderKey = 'Hr_Employee', + defaultValue = '', + onChange, +}: LeaveWaitingValidationSearchBarProps) => { + const I18n = useTranslator(); + const dispatch = useDispatch(); + + const {user} = useSelector(state => state.user); + const { + loadingLeaveToValidate, + moreLoadingLeaveToValidate, + isListEndLeaveToValidate, + leaveToValidateList, + } = useSelector(state => state.hr_leave); + + const fetchLeaveToValidateAPI = useCallback( + ({searchValue, page = 0}) => { + dispatch((fetchLeaveToValidate as any)({searchValue, user, page})); + }, + [dispatch, user], + ); + + return ( + + ); +}; + +export default LeaveWaitingValidationSearchBar; diff --git a/packages/apps/hr/src/components/templates/index.js b/packages/apps/hr/src/components/templates/index.js index 91697c9f6d..e443c8637c 100644 --- a/packages/apps/hr/src/components/templates/index.js +++ b/packages/apps/hr/src/components/templates/index.js @@ -31,6 +31,8 @@ export {default as ExpenseTypeSearchBar} from './ExpenseTypeSearchBar/ExpenseTyp export {default as ExpenseWaitingValidationSearchBar} from './ExpenseWaitingValidationSearchBar/ExpenseWaitingValidationSearchBar'; export {default as KilometricAllowParamSearchBar} from './KilometricAllowParamSearchBar/KilometricAllowParamSearchBar'; export {default as KilometricTypeSelectPicker} from './KilometricTypeSelectPicker/KilometricTypeSelectPicker'; +export {default as LeaveFilters} from './LeaveFilters/LeaveFilters'; +export {default as LeaveWaitingValidationSearchBar} from './LeaveWaitingValidationSearchBar/LeaveWaitingValidationSearchBar'; export {default as ManufOrderSearchBar} from './ManufOrderSearchBar/ManufOrderSearchBar'; export {default as OperationOrderSearchBar} from './OperationOrderSearchBar/OperationOrderSearchBar'; export {default as ProductSearchBar} from './ProductSearchBar/ProductSearchBar'; diff --git a/packages/apps/hr/src/features/asyncFunctions-index.ts b/packages/apps/hr/src/features/asyncFunctions-index.ts index 994ec42468..c8b71cbacd 100644 --- a/packages/apps/hr/src/features/asyncFunctions-index.ts +++ b/packages/apps/hr/src/features/asyncFunctions-index.ts @@ -51,6 +51,7 @@ export { searchKilometricAllowParam, updateExpenseDate, } from './kilometricAllowParamSlice'; +export {fetchLeave, fetchLeaveToValidate} from './leaveSlice'; export { searchManufOrder, searchOperationOrder, diff --git a/packages/apps/hr/src/features/index.js b/packages/apps/hr/src/features/index.js index fc9f62f40a..9928dc74c0 100644 --- a/packages/apps/hr/src/features/index.js +++ b/packages/apps/hr/src/features/index.js @@ -23,6 +23,7 @@ export {expenseLineReducer as expenseLine} from './expenseLineSlice'; export {expenseReducer as expense} from './expenseSlice'; export {expenseTypeReducer as expenseType} from './expenseTypeSlice'; export {kilometricAllowParamReducer as kilometricAllowParam} from './kilometricAllowParamSlice'; +export {leaveReducer as hr_leave} from './leaveSlice'; export {manufOrderReducer as hr_manufOrder} from './manufOrderSlice'; export {projectReducer as hr_project} from './projectSlice'; export {timerReducer as hr_timer} from './timerSlice'; diff --git a/packages/apps/hr/src/features/leaveSlice.js b/packages/apps/hr/src/features/leaveSlice.js new file mode 100644 index 0000000000..4583b30f09 --- /dev/null +++ b/packages/apps/hr/src/features/leaveSlice.js @@ -0,0 +1,95 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {createAsyncThunk, createSlice} from '@reduxjs/toolkit'; +import { + handlerApiCall, + generateInifiniteScrollCases, +} from '@axelor/aos-mobile-core'; +import { + fetchLeave as _fetchLeave, + fetchLeaveToValidate as _fetchLeaveToValidate, +} from '../api/leave-api'; + +export const fetchLeave = createAsyncThunk( + 'hr_leave/fetchLeave', + async function (data, {getState}) { + return handlerApiCall({ + fetchFunction: _fetchLeave, + data, + action: 'Hr_SliceAction_FetchLeave', + getState, + responseOptions: {isArrayResponse: true}, + }); + }, +); + +export const fetchLeaveToValidate = createAsyncThunk( + 'hr_leave/fetchLeaveToValidate', + async function (data, {getState}) { + return handlerApiCall({ + fetchFunction: _fetchLeaveToValidate, + data, + action: 'Hr_SliceAction_FetchLeaveToValidate', + getState, + responseOptions: {isArrayResponse: true, resturnTotalWithData: true}, + }); + }, +); + +const initialState = { + loadingMyLeave: true, + moreLoadingMyLeave: false, + isListEndMyLeave: false, + myLeaveList: [], + + loadingLeaveToValidate: true, + moreLoadingLeaveToValidate: false, + isListEndLeaveToValidate: false, + leaveToValidateList: [], + totalNumberLeaveToValidate: 0, +}; + +const leaveSlice = createSlice({ + name: 'hr_leave', + initialState, + extraReducers: builder => { + generateInifiniteScrollCases(builder, fetchLeave, { + loading: 'loadingMyLeave', + moreLoading: 'moreLoadingMyLeave', + isListEnd: 'isListEndMyLeave', + list: 'myLeaveList', + }); + generateInifiniteScrollCases( + builder, + fetchLeaveToValidate, + { + loading: 'loadingLeaveToValidate', + moreLoading: 'moreLoadingLeaveToValidate', + isListEnd: 'isListEndLeaveToValidate', + list: 'leaveToValidateList', + total: 'totalNumberLeaveToValidate', + }, + { + manageTotal: true, + }, + ); + }, +}); + +export const leaveReducer = leaveSlice.reducer; diff --git a/packages/apps/hr/src/i18n/en.json b/packages/apps/hr/src/i18n/en.json index a7fae7cf52..94d5dd7ac6 100644 --- a/packages/apps/hr/src/i18n/en.json +++ b/packages/apps/hr/src/i18n/en.json @@ -77,6 +77,9 @@ "Hr_ShowJustification": "Show justification", "Hr_See": "See", "Hr_Edit": "Edit", + "Hr_LeaveRequests": "Leave requests", + "Hr_Leaves": "Leaves", + "Hr_MyLeaves": "My leaves", "Hr_SliceAction_FetchExpenseLines": "fetch expense lines", "Hr_SliceAction_SearchDraftExpense": "fetch draft expenses", "Hr_SliceAction_FetchExpense": "fetch expenses", @@ -127,5 +130,7 @@ "Hr_SliceAction_CreateTimer": "create timer", "Hr_SliceAction_UpdateTimer": "update timer", "Hr_SliceAction_UpdateTimerStatus": "update timer status", - "Hr_SliceAction_DeleteTimer": "delete timer" + "Hr_SliceAction_DeleteTimer": "delete timer", + "Hr_SliceAction_FetchLeave": "fetch leave", + "Hr_SliceAction_FetchLeaveToValidate": "fetch leave to validate" } diff --git a/packages/apps/hr/src/i18n/fr.json b/packages/apps/hr/src/i18n/fr.json index 29787f2ec4..1ad1f7f4a2 100644 --- a/packages/apps/hr/src/i18n/fr.json +++ b/packages/apps/hr/src/i18n/fr.json @@ -77,6 +77,9 @@ "Hr_ShowJustification": "Afficher le justificatif", "Hr_See": "Voir", "Hr_Edit": "Modifier", + "Hr_LeaveRequests": "Demandes de congés", + "Hr_Leaves": "Congés", + "Hr_MyLeaves": "Mes congés", "Hr_SliceAction_FetchExpenseLines": "récupération des lignes de frais", "Hr_SliceAction_SearchDraftExpense": "récupération des notes de frais brouillon", "Hr_SliceAction_FetchExpense": "récupération des notes de frais", @@ -127,5 +130,7 @@ "Hr_SliceAction_CreateTimer": "création d'un chronomètre", "Hr_SliceAction_UpdateTimer": "mise à jour d'un chronomètre", "Hr_SliceAction_UpdateTimerStatus": "mise à jour du statut d'un chronomètre", - "Hr_SliceAction_DeleteTimer": "suppression d'un chronomètre" + "Hr_SliceAction_DeleteTimer": "suppression d'un chronomètre", + "Hr_SliceAction_FetchLeave": "récupération des congés", + "Hr_SliceAction_FetchLeaveToValidate": "récupération des congés à valider" } diff --git a/packages/apps/hr/src/index.ts b/packages/apps/hr/src/index.ts index fdd2dfb5fb..b2b8be07c6 100644 --- a/packages/apps/hr/src/index.ts +++ b/packages/apps/hr/src/index.ts @@ -21,6 +21,7 @@ import enTranslations from './i18n/en.json'; import frTranslations from './i18n/fr.json'; import ExpenseScreens from './screens/expense'; import TimesheetScreens from './screens/timesheet'; +import LeaveScreens from './screens/leaveRequests'; import { hr_modelAPI, hr_searchFields, @@ -94,10 +95,20 @@ export const HrModule: Module = { icon: 'credit-card-fill', screen: 'ExpenseListScreen', }, + hr_menu_leaveRequestsSeparator: { + title: 'Hr_LeaveRequests', + separator: true, + }, + hr_menu_leaves: { + title: 'Hr_Leaves', + icon: 'suitcase-fill', + screen: 'LeaveListScreen', + }, }, screens: { ...ExpenseScreens, ...TimesheetScreens, + ...LeaveScreens, }, reducers: {...hrReducers}, models: { @@ -116,5 +127,6 @@ export * from './components'; export * from './features/asyncFunctions-index'; export * from './screens/expense'; export * from './screens/timesheet'; +export * from './screens/leaveRequests'; export * from './types'; export * from './utils'; diff --git a/packages/apps/hr/src/models/objectFields.ts b/packages/apps/hr/src/models/objectFields.ts index 667f3ab9f4..5c42fb91d4 100644 --- a/packages/apps/hr/src/models/objectFields.ts +++ b/packages/apps/hr/src/models/objectFields.ts @@ -153,4 +153,18 @@ export const hr_modelAPI: ObjectFields = { }), ), }), + hr_leave: schemaContructor.object({ + statusSelect: schemaContructor.number(), + fromDateT: schemaContructor.string(), + toDateT: schemaContructor.string(), + duration: schemaContructor.number(), + leaveReason: schemaContructor.subObject().concat( + schemaContructor.object({ + name: schemaContructor.string(), + unitSelect: schemaContructor.number(), + }), + ), + company: schemaContructor.subObject('name'), + employee: schemaContructor.subObject('name'), + }), }; diff --git a/packages/apps/hr/src/models/searchFields.ts b/packages/apps/hr/src/models/searchFields.ts index 20251b49b2..6fcb997349 100644 --- a/packages/apps/hr/src/models/searchFields.ts +++ b/packages/apps/hr/src/models/searchFields.ts @@ -32,4 +32,5 @@ export const hr_searchFields: SearchFields = { hr_timer: ['project.fullName', 'projectTask.fullName', 'comments'], hr_timesheet: ['employee.name'], hr_timesheetLine: ['project.fullName', 'manufOrder.fullName'], + hr_leave: ['employee.name'], }; diff --git a/packages/apps/hr/src/models/sortFields.ts b/packages/apps/hr/src/models/sortFields.ts index 00e8dbf39f..02ffd20804 100644 --- a/packages/apps/hr/src/models/sortFields.ts +++ b/packages/apps/hr/src/models/sortFields.ts @@ -33,4 +33,5 @@ export const hr_sortFields: SortFields = { hr_activeTimer: ['-updatedOn'], hr_timesheet: ['-fromDate', '-toDate'], hr_timesheetLine: ['-date', '-duration'], + hr_leave: ['-fromDateT', '-startOnSelect'], }; diff --git a/packages/apps/hr/src/models/typeObjects.ts b/packages/apps/hr/src/models/typeObjects.ts index cc5c6c77d2..4e7842abf6 100644 --- a/packages/apps/hr/src/models/typeObjects.ts +++ b/packages/apps/hr/src/models/typeObjects.ts @@ -175,4 +175,62 @@ export const hr_typeObjects: ModuleSelections = [ }, }, }, + { + modelName: 'com.axelor.apps.hr.db.LeaveRequest', + fields: { + statusSelect: { + content: [ + { + key: 'Draft', + value: 1, + title: 'Hr_Status_Draft', + color: 'secondaryColor', + }, + { + key: 'WaitingValidation', + value: 2, + title: 'Hr_Status_WaitingValidation', + color: 'cautionColor', + }, + { + key: 'Validate', + value: 3, + title: 'Hr_Status_Validate', + color: 'successColor', + }, + { + key: 'Refused', + value: 4, + title: 'Hr_Status_Refused', + color: 'importantColor', + }, + { + key: 'Canceled', + value: 5, + title: 'Hr_Status_Canceled', + color: 'plannedColor', + }, + ], + }, + }, + }, + { + modelName: 'com.axelor.apps.hr.db.LeaveReason', + fields: { + unitSelect: { + content: [ + { + key: 'Days', + value: 1, + title: 'Hr_TimeUnit_Days', + }, + { + key: 'Hours', + value: 2, + title: 'Hr_TimeUnit_Hours', + }, + ], + }, + }, + }, ]; diff --git a/packages/apps/hr/src/screens/leaveRequests/LeaveListScreen.tsx b/packages/apps/hr/src/screens/leaveRequests/LeaveListScreen.tsx new file mode 100644 index 0000000000..ac9e1845b5 --- /dev/null +++ b/packages/apps/hr/src/screens/leaveRequests/LeaveListScreen.tsx @@ -0,0 +1,124 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useCallback, useMemo, useState} from 'react'; +import {useDispatch, useSelector, useTranslator} from '@axelor/aos-mobile-core'; +import {HeaderContainer, Screen, ScrollList} from '@axelor/aos-mobile-ui'; +import {LeaveActionCard, LeaveFilters} from '../../components'; +import {fetchLeave, fetchLeaveToValidate} from '../../features/leaveSlice'; +import {Leave} from '../../types'; + +const LeaveListScreen = ({}) => { + const I18n = useTranslator(); + const dispatch = useDispatch(); + + const [mode, setMode] = useState(Leave.mode.myLeaves); + const [selectedStatus, setSelectedStatus] = useState(null); + + const {user} = useSelector(state => state.user); + const { + loadingMyLeave, + moreLoadingMyLeave, + isListEndMyLeave, + myLeaveList, + loadingLeaveToValidate, + moreLoadingLeaveToValidate, + isListEndLeaveToValidate, + leaveToValidateList, + } = useSelector(state => state.hr_leave); + + const fetchLeaveAPI = useCallback( + (page = 0) => { + dispatch((fetchLeave as any)({userId: user?.id, selectedStatus, page})); + }, + [dispatch, selectedStatus, user?.id], + ); + + const fetchLeaveToValidateAPI = useCallback( + (page = 0) => { + dispatch((fetchLeaveToValidate as any)({user, page})); + }, + [dispatch, user], + ); + + const listToDisplay = useMemo(() => { + if (mode === Leave.mode.myLeaves) { + return { + list: myLeaveList, + loading: loadingMyLeave, + moreLoading: moreLoadingMyLeave, + isListEnd: isListEndMyLeave, + functionApi: fetchLeaveAPI, + }; + } else { + return { + list: leaveToValidateList, + loading: loadingLeaveToValidate, + moreLoading: moreLoadingLeaveToValidate, + isListEnd: isListEndLeaveToValidate, + functionApi: fetchLeaveToValidateAPI, + }; + } + }, [ + mode, + myLeaveList, + loadingMyLeave, + moreLoadingMyLeave, + isListEndMyLeave, + fetchLeaveAPI, + leaveToValidateList, + loadingLeaveToValidate, + moreLoadingLeaveToValidate, + isListEndLeaveToValidate, + fetchLeaveToValidateAPI, + ]); + + return ( + + + } + /> + ( + console.log('Card pressed.')} + onSend={() => console.log('Card send button pressed.')} + onValidate={() => console.log('Card validate button pressed.')} + /> + )} + fetchData={listToDisplay.functionApi} + moreLoading={listToDisplay.moreLoading} + isListEnd={listToDisplay.isListEnd} + translator={I18n.t} + /> + + ); +}; + +export default LeaveListScreen; diff --git a/packages/apps/hr/src/screens/leaveRequests/index.ts b/packages/apps/hr/src/screens/leaveRequests/index.ts new file mode 100644 index 0000000000..9cfec24fb8 --- /dev/null +++ b/packages/apps/hr/src/screens/leaveRequests/index.ts @@ -0,0 +1,32 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import LeaveListScreen from './LeaveListScreen'; + +export default { + LeaveListScreen: { + title: 'Hr_Leaves', + component: LeaveListScreen, + options: { + shadedHeader: false, + }, + isUsableOnShortcut: true, + }, +}; + +export {LeaveListScreen}; diff --git a/packages/apps/hr/src/types/index.ts b/packages/apps/hr/src/types/index.ts index e585fa2e79..f9720a3554 100644 --- a/packages/apps/hr/src/types/index.ts +++ b/packages/apps/hr/src/types/index.ts @@ -18,5 +18,6 @@ export {default as Expense} from './expense'; export {default as ExpenseLine} from './expenseLine'; +export {default as Leave} from './leave'; export {default as Time} from './time'; export {default as Timesheet} from './timesheet'; diff --git a/packages/apps/hr/src/types/leave.ts b/packages/apps/hr/src/types/leave.ts new file mode 100644 index 0000000000..3893b94312 --- /dev/null +++ b/packages/apps/hr/src/types/leave.ts @@ -0,0 +1,26 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class LeaveType { + static mode = { + myLeaves: 0, + leavesToValidate: 1, + }; +} + +export default LeaveType; From 11cafcde26376f3720d7b4346ea3534bcd6aae5d Mon Sep 17 00:00:00 2001 From: vhu-axelor <146069039+vhu-axelor@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:13:05 +0200 Subject: [PATCH 03/26] feat: add leave request details view (#681) * RM#82778 --- packages/apps/hr/src/api/index.ts | 1 + packages/apps/hr/src/api/leave-api.js | 9 ++ .../FromToDateDisplay/FromToDateDisplay.tsx | 74 ++++++++++ .../LeaveAvailableDuractionCard.tsx | 113 +++++++++++++++ .../apps/hr/src/components/atoms/index.js | 2 + .../LeaveDetailsButtons.tsx | 83 +++++++++++ .../LeaveDetailsHeader/LeaveDetailsHeader.tsx | 90 ++++++++++++ .../apps/hr/src/components/molecules/index.js | 2 + .../hr/src/features/asyncFunctions-index.ts | 2 +- packages/apps/hr/src/features/leaveSlice.js | 24 +++ .../hr/src/hooks/use-hr-header-actions.js | 14 ++ packages/apps/hr/src/i18n/en.json | 15 +- packages/apps/hr/src/i18n/fr.json | 15 +- packages/apps/hr/src/models/forms.ts | 2 +- packages/apps/hr/src/models/objectFields.ts | 10 ++ packages/apps/hr/src/models/typeObjects.ts | 28 ++++ .../leaveRequests/LeaveDetailsScreen.tsx | 137 ++++++++++++++++++ .../screens/leaveRequests/LeaveListScreen.tsx | 12 +- .../hr/src/screens/leaveRequests/index.ts | 10 ++ 19 files changed, 635 insertions(+), 8 deletions(-) create mode 100644 packages/apps/hr/src/components/atoms/FromToDateDisplay/FromToDateDisplay.tsx create mode 100644 packages/apps/hr/src/components/atoms/LeaveAvailableDuractionCard/LeaveAvailableDuractionCard.tsx create mode 100644 packages/apps/hr/src/components/molecules/LeaveDetailsButtons/LeaveDetailsButtons.tsx create mode 100644 packages/apps/hr/src/components/molecules/LeaveDetailsHeader/LeaveDetailsHeader.tsx create mode 100644 packages/apps/hr/src/screens/leaveRequests/LeaveDetailsScreen.tsx diff --git a/packages/apps/hr/src/api/index.ts b/packages/apps/hr/src/api/index.ts index a44e4e55fc..fd674801dd 100644 --- a/packages/apps/hr/src/api/index.ts +++ b/packages/apps/hr/src/api/index.ts @@ -45,6 +45,7 @@ export {searchExpenseType as searchExpenseTypeApi} from './expense-type-api'; export {searchKilometricAllowParam as searchKilometricAllowParamApi} from './kilometric-allow-param-api'; export { fetchLeave as fetchLeaveApi, + fetchLeaveById as fetchLeaveByIdApi, fetchLeaveToValidate as fetchLeaveToValidateApi, } from './leave-api'; export { diff --git a/packages/apps/hr/src/api/leave-api.js b/packages/apps/hr/src/api/leave-api.js index 9f2c1cf94f..ff123384d1 100644 --- a/packages/apps/hr/src/api/leave-api.js +++ b/packages/apps/hr/src/api/leave-api.js @@ -17,6 +17,7 @@ */ import { + createStandardFetch, createStandardSearch, getTypes, getSearchCriterias, @@ -89,3 +90,11 @@ export async function fetchLeaveToValidate({searchValue, user, page = 0}) { page, }); } + +export async function fetchLeaveById({leaveId}) { + return createStandardFetch({ + model: 'com.axelor.apps.hr.db.LeaveRequest', + id: leaveId, + fieldKey: 'hr_leave', + }); +} diff --git a/packages/apps/hr/src/components/atoms/FromToDateDisplay/FromToDateDisplay.tsx b/packages/apps/hr/src/components/atoms/FromToDateDisplay/FromToDateDisplay.tsx new file mode 100644 index 0000000000..753043e23c --- /dev/null +++ b/packages/apps/hr/src/components/atoms/FromToDateDisplay/FromToDateDisplay.tsx @@ -0,0 +1,74 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useCallback} from 'react'; +import {StyleSheet, View} from 'react-native'; +import {DateDisplay, useTypeHelpers, useTypes} from '@axelor/aos-mobile-core'; +import {Icon, Text} from '@axelor/aos-mobile-ui'; + +interface FromToDateDisplayProps { + fromDate: string; + startOnSelect: number; + toDate: string; + endOnSelect: number; +} + +const FromToDateDisplay = ({ + fromDate, + startOnSelect, + toDate, + endOnSelect, +}: FromToDateDisplayProps) => { + const {LeaveRequest} = useTypes(); + const {getItemTitle} = useTypeHelpers(); + + const renderDate = useCallback((date: string, subtitle: string) => { + return ( + + + {subtitle} + + ); + }, []); + + return ( + + {renderDate( + fromDate, + getItemTitle(LeaveRequest?.startOnSelect, startOnSelect), + )} + + {renderDate(toDate, getItemTitle(LeaveRequest?.endOnSelect, endOnSelect))} + + ); +}; + +const styles = StyleSheet.create({ + container: { + width: '90%', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + dateContainer: { + flexDirection: 'column', + alignItems: 'center', + }, +}); + +export default FromToDateDisplay; diff --git a/packages/apps/hr/src/components/atoms/LeaveAvailableDuractionCard/LeaveAvailableDuractionCard.tsx b/packages/apps/hr/src/components/atoms/LeaveAvailableDuractionCard/LeaveAvailableDuractionCard.tsx new file mode 100644 index 0000000000..0ebb2ee20c --- /dev/null +++ b/packages/apps/hr/src/components/atoms/LeaveAvailableDuractionCard/LeaveAvailableDuractionCard.tsx @@ -0,0 +1,113 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React, {useMemo} from 'react'; +import {StyleSheet, View} from 'react-native'; +import {useTranslator, useTypeHelpers, useTypes} from '@axelor/aos-mobile-core'; +import { + Card, + LabelText, + Text, + TextUnit, + useDigitFormat, + useThemeColor, +} from '@axelor/aos-mobile-ui'; + +interface LeaveAvailableDuractionCardProps { + style?: any; + reason: string; + availableLeave: number; + durationLeave: number; + durationUnitSelect: number; +} + +const LeaveAvailableDuractionCard = ({ + style, + reason, + availableLeave, + durationLeave, + durationUnitSelect, +}: LeaveAvailableDuractionCardProps) => { + const I18n = useTranslator(); + const Colors = useThemeColor(); + const formatNumber = useDigitFormat(); + const {LeaveReason} = useTypes(); + const {getItemTitle} = useTypeHelpers(); + + const styles = useMemo(() => { + return getStyles(Colors.secondaryColor.background); + }, [Colors]); + + return ( + + + + + {I18n.t('Hr_Available')} + + + + + {I18n.t('Hr_Duration')} + + + + + ); +}; + +const getStyles = (ruleColor: string) => + StyleSheet.create({ + cardContainer: { + width: '90%', + }, + labelText: { + fontSize: 16, + }, + container: { + flexDirection: 'row', + marginTop: 15, + }, + leaveContainer: { + flex: 1, + alignItems: 'center', + marginVertical: 10, + }, + horizontalRule: { + borderWidth: 0.5, + borderColor: ruleColor, + }, + titleText: { + paddingHorizontal: 10, + }, + }); + +export default LeaveAvailableDuractionCard; diff --git a/packages/apps/hr/src/components/atoms/index.js b/packages/apps/hr/src/components/atoms/index.js index 77f4d7f4d6..83a330bb46 100644 --- a/packages/apps/hr/src/components/atoms/index.js +++ b/packages/apps/hr/src/components/atoms/index.js @@ -18,6 +18,8 @@ export {default as ExpenseCard} from './ExpenseCard/ExpenseCard'; export {default as ExpenseLineCard} from './ExpenseLineCard/ExpenseLineCard'; +export {default as FromToDateDisplay} from './FromToDateDisplay/FromToDateDisplay'; +export {default as LeaveAvailableDuractionCard} from './LeaveAvailableDuractionCard/LeaveAvailableDuractionCard'; export {default as LeaveCard} from './LeaveCard/LeaveCard'; export {default as TimeCard} from './TimeCard/TimeCard'; export {default as TimesheetCard} from './TimesheetCard/TimesheetCard'; diff --git a/packages/apps/hr/src/components/molecules/LeaveDetailsButtons/LeaveDetailsButtons.tsx b/packages/apps/hr/src/components/molecules/LeaveDetailsButtons/LeaveDetailsButtons.tsx new file mode 100644 index 0000000000..38ae95e9c0 --- /dev/null +++ b/packages/apps/hr/src/components/molecules/LeaveDetailsButtons/LeaveDetailsButtons.tsx @@ -0,0 +1,83 @@ +/* + * Axelor Business Solutions + * + * Copyright (C) 2024 Axelor (). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import React from 'react'; +import {StyleSheet, View} from 'react-native'; +import {useTranslator, useTypes} from '@axelor/aos-mobile-core'; +import {Button, useThemeColor} from '@axelor/aos-mobile-ui'; + +interface LeaveDetailsButtonsProps { + statusSelect: number; +} + +const LeaveDetailsButtons = ({statusSelect}: LeaveDetailsButtonsProps) => { + const I18n = useTranslator(); + const Colors = useThemeColor(); + const {LeaveRequest} = useTypes(); + + if (statusSelect === LeaveRequest?.statusSelect.Draft) { + return ( + +