Compare commits

...

2 Commits

2 changed files with 121 additions and 3 deletions

View File

@ -7,6 +7,7 @@ import {
FormControl, FormControl,
Grid, Grid,
IconButton, IconButton,
InputAdornment,
InputLabel, InputLabel,
MenuItem, MenuItem,
Modal, Modal,
@ -18,7 +19,7 @@ import {
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { Close as CloseIcon } from '@mui/icons-material'; import { Close as CloseIcon } from '@mui/icons-material';
import React, { useContext, useState } from 'react'; import React, { useContext, useState, useEffect } from 'react';
import { I_S3Credentials } from '../../../interfaces/S3Types'; import { I_S3Credentials } from '../../../interfaces/S3Types';
import { I_Installation } from '../../../interfaces/InstallationTypes'; import { I_Installation } from '../../../interfaces/InstallationTypes';
import { InstallationsContext } from '../../../contexts/InstallationsContextProvider'; import { InstallationsContext } from '../../../contexts/InstallationsContextProvider';
@ -46,12 +47,38 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
const [openModalDeleteInstallation, setOpenModalDeleteInstallation] = const [openModalDeleteInstallation, setOpenModalDeleteInstallation] =
useState(false); useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const [batteryNumber, setBatteryNumber] = useState(0);
const [batterySerialNumbers, setBatterySerialNumbers] = useState<string[]>(
[]
);
const DeviceTypes = [ const DeviceTypes = [
{ id: 3, name: 'Growatt' }, { id: 3, name: 'Growatt' },
{ id: 4, name: 'Sinexcel' } { id: 4, name: 'Sinexcel' }
]; ];
const BATTERY_SN_PREFIX = 'PNR020125101';
const BATTERY_SN_SUFFIX_LENGTH = 4;
// Initialize battery data from props
useEffect(() => {
if (props.values.batteryNumber) {
setBatteryNumber(props.values.batteryNumber);
}
if (props.values.batterySerialNumbers) {
const serialNumbers = props.values.batterySerialNumbers
.split(',')
.filter((sn) => sn.trim() !== '')
.map((sn) => {
// If it has the prefix, extract only the suffix
if (sn.startsWith(BATTERY_SN_PREFIX)) {
return sn.substring(BATTERY_SN_PREFIX.length);
}
return sn;
});
setBatterySerialNumbers(serialNumbers);
}
}, []);
const installationContext = useContext(InstallationsContext); const installationContext = useContext(InstallationsContext);
const { const {
@ -72,6 +99,49 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
[name]: value [name]: value
}); });
}; };
const handleBatteryNumberChange = (e) => {
const inputValue = e.target.value;
// Only allow numeric input
if (inputValue === '' || /^\d+$/.test(inputValue)) {
const value = inputValue === '' ? 0 : parseInt(inputValue);
setBatteryNumber(value);
// Preserve existing serial numbers and adjust array size
const newSerialNumbers = Array.from({ length: value }, (_, index) => {
// Keep existing serial number if it exists, otherwise use empty string
return batterySerialNumbers[index] || '';
});
setBatterySerialNumbers(newSerialNumbers);
// Update formValues with preserved serial numbers
const fullSerialNumbers = newSerialNumbers
.map((suffix) => (suffix ? BATTERY_SN_PREFIX + suffix : ''))
.filter((sn) => sn !== '');
setFormValues({
...formValues,
batteryNumber: value,
batterySerialNumbers: fullSerialNumbers.join(',')
});
}
};
const handleBatterySerialNumberChange = (index: number, value: string) => {
// Only allow digits and limit to 3 characters
const sanitizedValue = value.replace(/\D/g, '').substring(0, BATTERY_SN_SUFFIX_LENGTH);
const updatedSerialNumbers = [...batterySerialNumbers];
updatedSerialNumbers[index] = sanitizedValue;
setBatterySerialNumbers(updatedSerialNumbers);
// Update formValues for persistence with full serial numbers (prefix + suffix)
const fullSerialNumbers = updatedSerialNumbers
.map((suffix) => (suffix ? BATTERY_SN_PREFIX + suffix : ''))
.filter((sn) => sn !== '');
setFormValues({
...formValues,
batterySerialNumbers: fullSerialNumbers.join(',')
});
};
const handleSubmit = () => { const handleSubmit = () => {
setLoading(true); setLoading(true);
setError(false); setError(false);
@ -186,7 +256,7 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
alignItems="stretch" alignItems="stretch"
spacing={3} spacing={3}
> >
<Grid item xs={12} md={12}> <Grid item xs={13} md={13}>
<CardContent> <CardContent>
<Box <Box
component="form" component="form"
@ -353,6 +423,52 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
/> />
</div> </div>
<div>
<TextField
label={
<FormattedMessage
id="batteryNumber"
defaultMessage="Battery Number"
/>
}
name="batteryNumber"
type="text"
value={batteryNumber === 0 ? '' : batteryNumber}
onChange={handleBatteryNumberChange}
variant="outlined"
fullWidth
placeholder="Enter number of batteries"
/>
</div>
{batteryNumber > 0 &&
batterySerialNumbers.map((serialNumber, index) => (
<div key={index}>
<TextField
label={`Battery Pack ${index + 1}`}
name={`batterySN${index + 1}`}
value={serialNumber}
onChange={(e) =>
handleBatterySerialNumberChange(index, e.target.value)
}
variant="outlined"
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
{BATTERY_SN_PREFIX}
</InputAdornment>
)
}}
inputProps={{
maxLength: BATTERY_SN_SUFFIX_LENGTH,
placeholder: '0000'
}}
helperText={`Enter ${BATTERY_SN_SUFFIX_LENGTH} digits`}
/>
</div>
))}
<div> <div>
<TextField <TextField
label={ label={
@ -507,4 +623,4 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
); );
} }
export default InformationSodistorehome; export default InformationSodistorehome;

View File

@ -16,6 +16,8 @@ export interface I_Installation extends I_S3Credentials {
inverterSN: string; inverterSN: string;
dataloggerSN: string; dataloggerSN: string;
batteryClusterNumber: number; batteryClusterNumber: number;
batteryNumber: number;
batterySerialNumbers: string;
parentId: number; parentId: number;
s3WriteKey: string; s3WriteKey: string;
s3WriteSecret: string; s3WriteSecret: string;