diff --git a/package-lock.json b/package-lock.json index 6aa5d16..cc72935 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "date-fns": "^4.1.0", "next": "15.3.4", "react": "^19.0.0", + "react-datepicker": "^8.4.0", "react-dom": "^19.0.0" }, "devDependencies": { @@ -236,6 +237,59 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.1", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.12.tgz", + "integrity": "sha512-kKlWNrpIQxF1B/a2MZvE0/uyKby4960yjO91W7nVyNKmmfNi62xU9HCjL1M1eWzx/LFj/VPSwJVbwQk9Pq/68A==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.3", + "@floating-ui/utils": "^0.2.9", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.3.tgz", + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -2319,6 +2373,15 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -5158,6 +5221,21 @@ "node": ">=0.10.0" } }, + "node_modules/react-datepicker": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.4.0.tgz", + "integrity": "sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.27.3", + "clsx": "^2.1.1", + "date-fns": "^4.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/react-dom": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", @@ -5794,6 +5872,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", diff --git a/package.json b/package.json index e611c47..51e409e 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "date-fns": "^4.1.0", "next": "15.3.4", "react": "^19.0.0", + "react-datepicker": "^8.4.0", "react-dom": "^19.0.0" }, "devDependencies": { diff --git a/src/app/components/ExchangeRateViewer.js b/src/app/components/ExchangeRateViewer.js index 94367f0..aeac624 100644 --- a/src/app/components/ExchangeRateViewer.js +++ b/src/app/components/ExchangeRateViewer.js @@ -1,26 +1,17 @@ "use client"; import React, { useState } from 'react'; -import { format } from 'date-fns'; - -function formatDisplayDate(dateStr) { - try { - let date; - if (dateStr.includes('/')) { - const [day, month, year] = dateStr.split('/'); - date = new Date(`${year}-${month}-${day}`); - } else { - date = new Date(dateStr); - } - return format(date, 'dd/MM/yyyy'); - } catch (e) { - return dateStr; - } -} +import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; +import { parse, isDate } from 'date-fns'; export default function ExchangeRateViewer({ defaultStartDate, defaultEndDate }) { - const [startDate, setStartDate] = useState(defaultStartDate); - const [endDate, setEndDate] = useState(defaultEndDate); + const [startDate, setStartDate] = useState( + defaultStartDate ? (isDate(defaultStartDate) ? defaultStartDate : parse(defaultStartDate, 'yyyy-MM-dd', new Date())) : null + ); + const [endDate, setEndDate] = useState( + defaultEndDate ? (isDate(defaultEndDate) ? defaultEndDate : parse(defaultEndDate, 'yyyy-MM-dd', new Date())) : null + ); const [selectedBank, setSelectedBank] = useState('bidv'); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); @@ -37,8 +28,8 @@ export default function ExchangeRateViewer({ defaultStartDate, defaultEndDate }) setResults([]); setShowTable(false); try { - const start = new Date(startDate); - const end = new Date(endDate); + const start = startDate; + const end = endDate; if (start > end) { setError('Start date cannot be after end date'); setIsLoading(false); @@ -110,25 +101,27 @@ export default function ExchangeRateViewer({ defaultStartDate, defaultEndDate })