Compare commits
2 Commits
8a2be78c01
...
5f1bcdb0c1
| Author | SHA1 | Date |
|---|---|---|
|
|
5f1bcdb0c1 | |
|
|
022fc6f576 |
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue