Skip to content

Commit ebb8f14

Browse files
Merge pull request #4493 from OneCommunityGlobal/SaiKrishna_FixAddMaterials
Sai krishna fix add materials
2 parents 82939c5 + a6c6a2d commit ebb8f14

5 files changed

Lines changed: 114 additions & 18 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
"leaflet": "^1.9.4",
7171
"leaflet.heat": "^0.2.0",
7272
"leaflet.markercluster": "^1.5.3",
73-
"lodash": "^4.17.23",
73+
"libphonenumber-js": "^1.12.31",
74+
"lodash": "^4.17.21",
7475
"lucide-react": "^0.484.0",
7576
"micromatch": "^4.0.8",
7677
"moment": "^2.30.1",

src/components/Auth/PermissionWatcher.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState, useRef } from 'react';
1+
import { useEffect, useState } from 'react';
22
import { useSelector, useDispatch } from 'react-redux';
33
import axios from 'axios';
44
import { ENDPOINTS } from '~/utils/URL';
@@ -82,6 +82,8 @@ function PermissionWatcher() {
8282
if (!isAuthenticated || !flagReady) return;
8383
if (!userProfile) return;
8484
if (isInitialLogin) return;
85+
// Don't trigger when permissions haven't been loaded yet (e.g. on /bmdashboard/login before profile fetch)
86+
if (userProfile?.permissions === undefined || userProfile?.permissions === null) return;
8587

8688
const permissionsChangedMidSession =
8789
isAcknowledged === false && !forceLogoutAt && initialAcknowledgedState !== false;

src/components/BMDashboard/AddMaterial/AddMaterial.jsx

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ModalFooter,
1313
} from 'reactstrap';
1414
import PhoneInput from 'react-phone-input-2';
15+
import { parsePhoneNumberFromString } from 'libphonenumber-js/max';
1516
import { toast } from 'react-toastify';
1617
import { useDispatch, useSelector } from 'react-redux';
1718
import Joi from 'joi-browser';
@@ -47,6 +48,7 @@ export default function AddMaterialForm() {
4748
const [formData, setFormData] = useState(initialFormState);
4849
const [areaCode, setAreaCode] = useState('1');
4950
const [phoneNumber, setPhoneNumber] = useState('');
51+
const [phoneValid, setPhoneValid] = useState(true);
5052
const [uploadedFiles, setUploadedFiles] = useState([]); // log here for correct state snapshot (will show each render)
5153
const [errors, setErrors] = useState({});
5254
const history = useHistory();
@@ -59,6 +61,7 @@ export default function AddMaterialForm() {
5961
const [showTextbox, setShowTextbox] = useState(false);
6062
const [selectedUnit, setSelectedUnit] = useState('');
6163
const [newUnit, setNewUnit] = useState('');
64+
const [dateError, setDateError] = useState(null);
6265
const units = useSelector(state => state.bmInvUnits.list);
6366
// console.log(materialTypes);
6467
// console.log(units)
@@ -139,10 +142,27 @@ export default function AddMaterialForm() {
139142
};
140143

141144
const handleInputChange = (name, value) => {
142-
setFormData(prevData => ({
143-
...prevData,
144-
[name]: value,
145-
}));
145+
if (name === 'purchaseDate') {
146+
const today = new Date().toLocaleDateString('en-CA');
147+
if (value && value > today) {
148+
setDateError("Purchase date should be equal or earlier to today's date");
149+
setFormData(prevData => ({
150+
...prevData,
151+
[name]: '',
152+
}));
153+
} else {
154+
setDateError(null);
155+
setFormData(prevData => ({
156+
...prevData,
157+
[name]: value,
158+
}));
159+
}
160+
} else {
161+
setFormData(prevData => ({
162+
...prevData,
163+
[name]: value,
164+
}));
165+
}
146166
};
147167

148168
const { unitPrice, quantity, taxes, shippingFee } = formData;
@@ -154,16 +174,73 @@ export default function AddMaterialForm() {
154174
const totalTax = calculateTotalTax(Number(taxes), totalPrice);
155175
const totalPriceWithShipping = (totalPrice + totalTax + Number(shippingFee)).toFixed(2);
156176

157-
const phoneChange = (name, phone) => {
177+
const phoneChange = (name, phone, countryData) => {
178+
const dialCode = countryData.dialCode;
179+
const countryCode = countryData.countryCode.toUpperCase();
180+
181+
// Get the national number (remove dial code from beginning)
182+
let nationalNumber = '';
183+
if (phone && phone.startsWith(dialCode)) {
184+
nationalNumber = phone.slice(dialCode.length);
185+
} else if (phone) {
186+
nationalNumber = phone;
187+
}
188+
189+
// Check if country changed (dial code in formData is different from current)
190+
const previousDialCode = formData.areaCode ? formData.areaCode.replace('+', '') : '1';
191+
const countryChanged = previousDialCode !== dialCode;
192+
193+
// If country changed, reset to just the dial code
194+
if (countryChanged && formData.phoneNumber) {
195+
setFormData(prevData => ({
196+
...prevData,
197+
[name]: dialCode,
198+
areaCode: `+${dialCode}`,
199+
}));
200+
setPhoneValid(true);
201+
return;
202+
}
203+
158204
setFormData(prevData => ({
159205
...prevData,
160206
[name]: phone,
207+
areaCode: `+${dialCode}`,
161208
}));
209+
210+
// If no national number entered, consider it valid (optional field)
211+
if (!nationalNumber) {
212+
setPhoneValid(true);
213+
return;
214+
}
215+
216+
// Validate phone number
217+
try {
218+
const fullNumber = `+${dialCode}${nationalNumber}`;
219+
const phoneNumberObj = parsePhoneNumberFromString(fullNumber, countryCode);
220+
221+
if (phoneNumberObj) {
222+
const isValidFormat = phoneNumberObj.isValid();
223+
const numberType = phoneNumberObj.getType();
224+
225+
// Number must be valid AND must have a recognized type (MOBILE, FIXED_LINE, etc.)
226+
const hasValidType = numberType !== undefined;
227+
setPhoneValid(isValidFormat && hasValidType);
228+
} else {
229+
setPhoneValid(false);
230+
}
231+
} catch (error) {
232+
setPhoneValid(false);
233+
}
162234
};
163235

164236
const handleSubmit = async event => {
165237
event.preventDefault();
166238
const validationErrors = validate(formData);
239+
if (!phoneValid) {
240+
toast.error('Invalid phone number for the selected country');
241+
return;
242+
}
243+
167244
setErrors(validationErrors || {});
168245

169246
if (validationErrors) {
@@ -405,7 +482,7 @@ export default function AddMaterialForm() {
405482
<Input
406483
id="purchase-date"
407484
type="date"
408-
name="purchase-date"
485+
name="purchaseDate"
409486
value={formData.purchaseDate}
410487
onChange={event => handleInputChange('purchaseDate', event.target.value)}
411488
/>
@@ -414,6 +491,9 @@ export default function AddMaterialForm() {
414491
Enter Date
415492
</Label>
416493
)}
494+
<Label for="purchaseDateErr" sm={12} className={`${styles.materialFormError}`}>
495+
{dateError}
496+
</Label>
417497
</FormGroup>
418498
</div>
419499
<div className={`${styles.addMaterialFlexGroup}`}>
@@ -440,15 +520,23 @@ export default function AddMaterialForm() {
440520
/>
441521
</FormGroup>
442522
</div>
443-
444-
<PhoneInput
445-
country="US"
446-
regions={['america', 'europe', 'asia', 'oceania', 'africa']}
447-
limitMaxLength="true"
448-
value={formData.phoneNumber}
449-
onChange={phone => phoneChange('phoneNumber', phone)}
450-
inputStyle={{ height: 'auto', width: '40%', fontSize: 'inherit' }}
451-
/>
523+
<FormGroup>
524+
<Label for="Phone Number">Phone Number</Label>
525+
<div>
526+
<PhoneInput
527+
country="us"
528+
value={formData.phoneNumber}
529+
onChange={(phone, countryData) => phoneChange('phoneNumber', phone, countryData)}
530+
enableLongNumbers={false}
531+
inputStyle={{ height: 'auto', width: '40%', fontSize: 'inherit' }}
532+
/>
533+
{!phoneValid && formData.phoneNumber && (
534+
<Label className={`${styles.materialFormError}`}>
535+
Invalid phone number for the selected country
536+
</Label>
537+
)}
538+
</div>
539+
</FormGroup>
452540
<FormGroup>
453541
<Label for="imageUpload">Upload Material Picture</Label>
454542
<DragAndDrop

src/components/BMDashboard/_tests_/AddMaterial.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ vi.mock('react-phone-input-2', () => ({
4343
<input
4444
data-testid="phone-input"
4545
value={props.value}
46-
onChange={e => props.onChange(e.target.value)}
46+
onChange={e => props.onChange(e.target.value, { dialCode: '1', countryCode: 'us' })}
4747
placeholder="Phone number"
4848
/>
4949
);

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8710,6 +8710,11 @@ levn@^0.4.1:
87108710
prelude-ls "^1.2.1"
87118711
type-check "~0.4.0"
87128712

8713+
libphonenumber-js@^1.12.31:
8714+
version "1.12.31"
8715+
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.12.31.tgz#3cdb45641c6b77228dd1238f3d810c3bb5d91199"
8716+
integrity sha512-Z3IhgVgrqO1S5xPYM3K5XwbkDasU67/Vys4heW+lfSBALcUZjeIIzI8zCLifY+OCzSq+fpDdywMDa7z+4srJPQ==
8717+
87138718
lines-and-columns@^1.1.6:
87148719
version "1.2.4"
87158720
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"

0 commit comments

Comments
 (0)