Skip to content

Commit

Permalink
feat: add requestLineListScreen
Browse files Browse the repository at this point in the history
  • Loading branch information
gca-axelor committed Jan 2, 2025
1 parent 1295618 commit 38f722d
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 7 deletions.
37 changes: 32 additions & 5 deletions packages/apps/purchase/src/api/purchase-request-line-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,49 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import {createStandardSearch} from '@axelor/aos-mobile-core';
import {
createStandardSearch,
getSearchCriterias,
} from '@axelor/aos-mobile-core';

const createPurchaseRequestLineCriteria = purchaseRequestId => {
return [
const createPurchaseRequestLineCriteria = ({
searchValue,
purchaseRequestId,
newProduct,
}) => {
const criterias = [
getSearchCriterias('purchase_purchaseRequestLine', searchValue),
{
fieldName: 'purchaseRequest.id',
operator: '=',
value: purchaseRequestId,
},
];

if (newProduct != null) {
criterias.push({
fieldName: 'newProduct',
operator: newProduct ? '=' : '!=',
value: true,
});
}

return criterias;
};

export async function searchPurchaseRequestLine({page = 0, purchaseRequestId}) {
export async function searchPurchaseRequestLine({
page = 0,
searchValue,
purchaseRequestId,
newProduct,
}) {
return createStandardSearch({
model: 'com.axelor.apps.purchase.db.PurchaseRequestLine',
criteria: createPurchaseRequestLineCriteria(purchaseRequestId),
criteria: createPurchaseRequestLineCriteria({
searchValue,
purchaseRequestId,
newProduct,
}),
fieldKey: 'purchase_purchaseRequestLine',
sortKey: 'purchase_purchaseRequestLine',
page,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import React, {useMemo} from 'react';
import {StyleSheet, TouchableOpacity, View} from 'react-native';
import {useTranslator} from '@axelor/aos-mobile-core';
import {useNavigation, useTranslator} from '@axelor/aos-mobile-core';
import {
Card,
Icon,
Expand All @@ -33,6 +33,7 @@ interface PurchaseSeeLinesButtonProps {

const PurchaseSeeLinesButton = ({numberLines}: PurchaseSeeLinesButtonProps) => {
const I18n = useTranslator();
const navigation = useNavigation();
const Colors = useThemeColor();

const styles = useMemo(
Expand All @@ -41,7 +42,9 @@ const PurchaseSeeLinesButton = ({numberLines}: PurchaseSeeLinesButtonProps) => {
);

return (
<TouchableOpacity onPress={() => {}} activeOpacity={0.9}>
<TouchableOpacity
onPress={() => navigation.navigate('RequestLineListScreen', {})}
activeOpacity={0.9}>
<Card style={styles.container}>
<Text style={styles.text}>{I18n.t('Purchase_SeeLines')}</Text>
<View style={styles.rightContainer}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2024 Axelor (<http://axelor.com>).
*
* 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 <http://www.gnu.org/licenses/>.
*/

import React, {useMemo} from 'react';
import {StyleSheet} from 'react-native';
import {
ObjectCard,
TextUnit,
usePriceFormat,
useThemeColor,
} from '@axelor/aos-mobile-ui';

interface RequestLineCardProps {
style?: any;
productName?: string;
unit?: string;
qty?: string;
newProduct?: boolean;
}

const RequestLineCard = ({
style,
productName,
unit,
qty,
newProduct,
}: RequestLineCardProps) => {
const priceFormat = usePriceFormat();
const Colors = useThemeColor();

const borderStyle = useMemo(() => {
if (newProduct) {
return getStyles(Colors.plannedColor.background)?.border;
}
}, [Colors.plannedColor.background, newProduct]);

return (
<ObjectCard
style={[borderStyle, style]}
upperTexts={{
items: [
{
isTitle: true,
displayText: productName,
},
],
}}
sideBadges={{
items: [
{
customComponent: (
<TextUnit unit={unit} value={priceFormat(qty)} fontSize={20} />
),
},
],
}}
/>
);
};

const getStyles = (color: string) =>
StyleSheet.create({
border: {borderLeftWidth: 7, borderLeftColor: color},
});

export default RequestLineCard;
1 change: 1 addition & 0 deletions packages/apps/purchase/src/components/atoms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export {default as DropdownRequestCharacteristics} from './DropdownRequestCharac
export {default as RequestSeeLinesButton} from './RequestSeeLinesButton/RequestSeeLinesButton';
export {default as RequestCard} from './RequestCard/RequestCard';
export {default as RequestHeader} from './RequestHeader/RequestHeader';
export {default as RequestLineCard} from './RequestLineCard/RequestLineCard';
3 changes: 3 additions & 0 deletions packages/apps/purchase/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"Purchase_Accept": "Accept",
"Purchase_Refuse": "Refuse",
"Purchase_NoInformationAvailable": "No information available",
"Purchase_AddProduct": "Add product",
"Purchase_NewProduct": "New product",
"Purchase_ExistingProduct": "Existing product",
"Purchase_SliceAction_SearchPurchaseRequest": "search purchase request",
"Purchase_SliceAction_SearchSupplier": "search supplier",
"Purchase_SliceAction_GetPurchaseRequest": "get purchase request",
Expand Down
3 changes: 3 additions & 0 deletions packages/apps/purchase/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"Purchase_Accept": "Accepter",
"Purchase_Refuse": "Refuser",
"Purchase_NoInformationAvailable": "Aucune information disponible",
"Purchase_AddProduct": "Ajouter un produit",
"Purchase_NewProduct": "Nouveau produit",
"Purchase_ExistingProduct": "Produit existant",
"Purchase_SliceAction_SearchPurchaseRequest": "recherche sur les demandes d'achat",
"Purchase_SliceAction_SearchSupplier": "recherche sur les fournisseurs",
"Purchase_SliceAction_GetPurchaseRequest": "récupération de la demande d'achat",
Expand Down
6 changes: 6 additions & 0 deletions packages/apps/purchase/src/models/objectFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ export const purchase_modelAPI: ObjectFields = {
purchase_supplier: schemaContructor.object({
simpleFullName: schemaContructor.string(),
}),
purchase_purchaseRequestLine: schemaContructor.object({
product: schemaContructor.subObject(),
unit: schemaContructor.subObject(),
quantity: schemaContructor.string(),
newProduct: schemaContructor.boolean(),
}),
};
1 change: 1 addition & 0 deletions packages/apps/purchase/src/models/searchFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ import {SearchFields} from '@axelor/aos-mobile-core';
export const purchase_searchFields: SearchFields = {
purchase_purchaseRequest: ['purchaseRequestSeq', 'company.name'],
purchase_supplier: ['simpleFullName'],
purchase_purchaseRequestLine: ['product.fullName'],
};
21 changes: 21 additions & 0 deletions packages/apps/purchase/src/models/typeObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,25 @@ export const purchase_typeObjects: ModuleSelections = [
},
},
},
{
modelName: 'com.axelor.apps.purchase.db.PurchaseRequestLine',
fields: {
newProduct: {
content: [
{
key: 'NewProduct',
value: true,
title: 'Purchase_NewProduct',
color: 'plannedColor',
},
{
key: 'ExistingProduct',
value: false,
title: 'Purchase_ExistingProduct',
color: 'secondaryColor',
},
],
},
},
},
];
100 changes: 100 additions & 0 deletions packages/apps/purchase/src/screens/RequestLineListScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2024 Axelor (<http://axelor.com>).
*
* 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 <http://www.gnu.org/licenses/>.
*/

import React, {useMemo, useState} from 'react';
import {ChipSelect, Screen} from '@axelor/aos-mobile-ui';
import {
SearchListView,
useSelector,
useTranslator,
useTypeHelpers,
useTypes,
} from '@axelor/aos-mobile-core';
import {RequestHeader, RequestLineCard} from '../components';
import {searchPurchaseRequestLine} from '../features/purchaseRequestLineSlice';

const RequestLineListScreen = () => {
const I18n = useTranslator();
const {PurchaseRequestLine} = useTypes();
const {getSelectionItems} = useTypeHelpers();

const {purchaseRequest} = useSelector(
state => state.purchase_purchaseRequest,
);
const {
loadingPurchaseRequestLines,
moreLoadingPurchaseRequestLine,
isListEndPurchaseRequestLine,
purchaseRequestLineList,
} = useSelector(state => state.purchase_purchaseRequestLine);

const [selectedStatus, setSelectedStatus] = useState([]);

const statusList = useMemo(
() => getSelectionItems(PurchaseRequestLine?.newProduct, selectedStatus),
[PurchaseRequestLine?.newProduct, getSelectionItems, selectedStatus],
);

const sliceFunctionData = useMemo(
() => ({
purchaseRequestId: purchaseRequest.id,
newProduct: selectedStatus[0]?.value,
}),
[purchaseRequest.id, selectedStatus],
);

return (
<Screen removeSpaceOnTop={true}>
<SearchListView
topFixedItems={<RequestHeader />}
actionList={[
{
iconName: 'plus',
title: I18n.t('Purchase_AddProduct'),
onPress: () => {},
},
]}
chipComponent={
<ChipSelect
mode="switch"
onChangeValue={setSelectedStatus}
selectionItems={statusList}
/>
}
expandableFilter={false}
searchPlaceholder={I18n.t('Base_Search')}
list={purchaseRequestLineList}
loading={loadingPurchaseRequestLines}
moreLoading={moreLoadingPurchaseRequestLine}
isListEnd={isListEndPurchaseRequestLine}
sliceFunction={searchPurchaseRequestLine}
sliceFunctionData={sliceFunctionData}
renderListItem={({item}) => (
<RequestLineCard
productName={item.product?.fullName}
qty={item.quantity}
unit={item.unit?.name}
newProduct={item.newProduct}
/>
)}
/>
</Screen>
);
};

export default RequestLineListScreen;
8 changes: 8 additions & 0 deletions packages/apps/purchase/src/screens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import RequestDetailsScreen from './RequestDetailsScreen';
import RequestLineListScreen from './RequestLineListScreen';
import RequestListScreen from './RequestListScreen';

export default {
Expand All @@ -35,6 +36,13 @@ export default {
shadedHeader: false,
},
},
RequestLineListScreen: {
title: 'Purchase_InternalRequests',
component: RequestLineListScreen,
options: {
shadedHeader: false,
},
},
};

export {RequestDetailsScreen};
Expand Down

0 comments on commit 38f722d

Please sign in to comment.