購入日・賞味期限コンポーネントの実装

feature-frontend-dateselect-fix
Masaharu.Kato 4 months ago
parent 615f9bd607
commit a48247def5
  1. 69
      frontend/src/components/BuyDialog.tsx
  2. 80
      frontend/src/components/BuyExpDateSelect.tsx
  3. 145
      frontend/src/pages/StockPage.tsx
  4. 4
      frontend/src/pages/TaskListPage.tsx

@ -9,6 +9,7 @@ import {
Box,
} from '@mui/material';
import { NewStock } from '../types/types';
import BuyExpDateSelect from './BuyExpDateSelect';
/*import DatePicker, { registerLocale } from 'react-datepicker';
import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート*/
@ -89,73 +90,9 @@ const BuyDialog = ({
sx={{ marginBottom: 2 }}
/>
{/* 購入日・消費期限を横並びに */}
<Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
{/* 購入日入力フィールド */}
<TextField
margin="dense"
label="購入日"
type="date"
fullWidth
value={newStock.buyDate ? newStock.buyDate.substring(0, 10) : ''}
onChange={(e) =>
setNewStock({ ...newStock, buyDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
/>
{/*<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.buyDate ? new Date(newStock.buyDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, buyDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal // ← 他の文字との重なり対策
/>*/}
{/* 購入日・賞味期限入力 */}
<BuyExpDateSelect newStock={newStock} setNewStock={({buyDate, expDate}) => setNewStock({...newStock, buyDate, expDate}) } />
{/* 消費・賞味期限入力フィールド */}
<TextField
margin="dense"
label="消費・賞味期限"
type="date"
fullWidth
value={newStock.expDate ? newStock.expDate.substring(0, 10) : ''}
onChange={(e) =>
setNewStock({ ...newStock, expDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
InputProps={{
inputProps: {
min: newStock.buyDate ? newStock.buyDate.substring(0, 10) : undefined,
}
}}
/>
{/*<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.expDate ? new Date(newStock.expDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, expDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal
/>*/}
</Box>
{/* 購入店舗入力フィールド */}
<TextField
margin="dense"

@ -0,0 +1,80 @@
import { Box, TextField } from "@mui/material"
// 日付文字列(時間を含む可能性がある)から日付部分だけを返す
const parseDate = ((date: string) => date ? date.substring(0, 10) : '')
// 今日の日付
const today = parseDate(new Date().toISOString());
// 日付文字列で早いほうを返す(空でないものは除く)
const validateBuyDate = ((buyDate: string) => {
// console.log('validateBuyDate:', buyDate)
if (!buyDate) { // 購入日が未設定の場合は今日の日付を入れておく
return today;
}
return parseDate(buyDate);
})
// 日付文字列で早いほうを返す(空でないものは除く)
const validateExpDate = ((buyDate: string, expDate: string) => {
// console.log('validateExpDate:', buyDate, expDate)
if (!expDate) { // 賞味期限が未設定の場合そのまま未設定にする
return '';
}
const buyDateParsed = validateBuyDate(buyDate);
const expDateParsed = parseDate(expDate);
// 購入日以降となるようにする
return buyDateParsed > expDateParsed ? buyDateParsed : expDateParsed;
})
const BuyExpDateSelect = ({
newStock,
setNewStock,
}: {
newStock: {buyDate: string, expDate: string},
setNewStock: (tobuy: {buyDate: string, expDate: string}) => void,
}) => {
{/* 購入日・消費期限を横並びに */ }
return <Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
{/* 購入日入力フィールド */}
<TextField
margin="dense"
label="購入日"
type="date"
fullWidth
value={validateBuyDate(newStock.buyDate)}
onChange={(e) =>
setNewStock({ ...newStock, buyDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
InputProps={{
inputProps: {
max: today,
}
}}
/>
{/* 消費・賞味期限入力フィールド */}
<TextField
margin="dense"
label="消費・賞味期限"
type="date"
fullWidth
value={validateExpDate(newStock.buyDate, newStock.expDate)}
onChange={(e) =>
setNewStock({ ...newStock, expDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
InputProps={{
inputProps: {
min: validateBuyDate(newStock.buyDate),
}
}}
/>
</Box>
}
export default BuyExpDateSelect;

@ -31,6 +31,7 @@ import { Add as AddIcon } from '@mui/icons-material';
/*import DatePicker, { registerLocale } from 'react-datepicker';
import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート*/
import { useMessage } from '../components/MessageContext';
import BuyExpDateSelect from '../components/BuyExpDateSelect';
/*// yyyy-MM-dd形式で返す関数
const formatDateLocal = (date: Date) => {
@ -479,79 +480,9 @@ const StockPage: React.FC = () => {
onChange={handleChange}
/>
{/* 購入日・消費期限を横並びに */}
<Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
{/* 購入日 */}
<TextField
margin="normal"
label="購入日"
type="date"
fullWidth
name="buyDate"
value={editStock.buyDate ? editStock.buyDate.substring(0, 10) : ''}
onChange={(e) => setEditStock({ ...editStock, buyDate: e.target.value })}
InputLabelProps={{ shrink: true }}
/>
{/*<DatePicker
selected={editStock.buyDate ? new Date(editStock.buyDate) : null}
onChange={(date) => {
if (editStock) {
setEditStock({
...editStock,
buyDate: date ? formatDateLocal(date) : '',
});
}
}}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="normal"
label="購入日 (yyyy/MM/dd)"
fullWidth
name="buyDate"
/>
}
isClearable
/>*/}
{/* 消費・賞味期限 */}
<TextField
margin="normal"
label="消費・賞味期限"
type="date"
fullWidth
name="expDate"
value={editStock.expDate ? editStock.expDate.substring(0, 10) : ''}
onChange={(e) => setEditStock({ ...editStock, expDate: e.target.value })}
InputLabelProps={{ shrink: true }}
InputProps={{
inputProps: {
min: newStock.buyDate ? newStock.buyDate.substring(0, 10) : undefined,
}
}}
/>
{/* 購入日・賞味期限入力 */}
<BuyExpDateSelect newStock={editStock} setNewStock={({ buyDate, expDate }) => setEditStock({ ...editStock, buyDate, expDate })} />
{/*<DatePicker
selected={editStock.expDate ? new Date(editStock.expDate) : null}
onChange={(date) => {
if (editStock) {
setEditStock({
...editStock,
expDate: date ? formatDateLocal(date) : '',
});
}
}}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="normal"
label="消費・賞味期限 (yyyy/MM/dd)"
fullWidth
name="expDate"
/>
}
isClearable
/>*/}
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, mt: 3, mb: 2 }}>
<Button onClick={() => { setIsEditOpen(false); setSelectedRow(null); }}>
@ -769,72 +700,10 @@ const StockPage: React.FC = () => {
value={newStock.shop}
onChange={(e) => setNewStock({ ...newStock, shop: e.target.value })}
/>
{/* 購入日・消費期限を横並びに */}
<Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
{/* 購入日入力フィールド */}
<TextField
margin="dense"
label="購入日"
type="date"
fullWidth
value={newStock.buyDate ? newStock.buyDate.substring(0, 10) : ''}
onChange={(e) =>
setNewStock({ ...newStock, buyDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
/>
{/*<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.buyDate ? new Date(newStock.buyDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, buyDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal // ← 他の文字との重なり対策
/>*/}
{/* 消費・賞味期限入力フィールド */}
<TextField
margin="dense"
label="消費・賞味期限"
type="date"
fullWidth
value={newStock.expDate ? newStock.expDate.substring(0, 10) : ''}
onChange={(e) =>
setNewStock({ ...newStock, expDate: e.target.value })
}
InputLabelProps={{ shrink: true }}
InputProps={{
inputProps: {
min: newStock.buyDate ? newStock.buyDate.substring(0, 10) : undefined,
}
}}
/>
{/*<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.expDate ? new Date(newStock.expDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, expDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal
/>*/}
</Box>
{/* 購入日・賞味期限入力 */}
<BuyExpDateSelect newStock={newStock} setNewStock={({ buyDate, expDate }) => setNewStock({ ...newStock, buyDate, expDate })} />
</Box>
</DialogContent>
<DialogActions>

@ -69,8 +69,8 @@ const TaskListPage: React.FC = () => {
amount: '', // 購入数量(ここではstring)
price: '', // ここではstring
shop: '',
buyDate: new Date().toISOString(),
expDate: '',
buyDate: '', // 日付選択側で今日の日付がデフォルトで選択されている
expDate: '', // 未設定状態
});
//削除確認ダイアログの表示状態

Loading…
Cancel
Save