diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index a8cc84a3..bae02004 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -37,6 +37,7 @@
"react-router-dom": "^6.26.2",
"react-router-hash-link": "^2.4.3",
"react-scripts": "^5.0.1",
+ "react-select": "^5.8.1",
"reactjs-popup": "^2.0.6"
},
"devDependencies": {
@@ -2568,6 +2569,135 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
+ "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/serialize": "^1.2.0",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.13.1",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz",
+ "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/sheet": "^1.4.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
+ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
+ "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.13.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
+ "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.12.0",
+ "@emotion/cache": "^11.13.0",
+ "@emotion/serialize": "^1.3.1",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
+ "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/unitless": "^0.10.0",
+ "@emotion/utils": "^1.4.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
+ "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
+ "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz",
+ "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
+ "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
+ "license": "MIT"
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -4778,6 +4908,15 @@
"@types/react-router-dom": "^5.3.0"
}
},
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.11",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
+ "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@@ -9121,6 +9260,12 @@
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
+ "license": "MIT"
+ },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -9811,6 +9956,21 @@
"he": "bin/he"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -16470,6 +16630,43 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/react-select": {
+ "version": "5.8.1",
+ "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.1.tgz",
+ "integrity": "sha512-RT1CJmuc+ejqm5MPgzyZujqDskdvB9a9ZqrdnVLsvAHjJ3Tj0hELnLeVPQlmYdVKCdCpxanepl6z7R5KhXhWzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.0",
+ "@emotion/cache": "^11.4.0",
+ "@emotion/react": "^11.8.1",
+ "@floating-ui/dom": "^1.0.1",
+ "@types/react-transition-group": "^4.4.0",
+ "memoize-one": "^6.0.0",
+ "prop-types": "^15.6.0",
+ "react-transition-group": "^4.3.0",
+ "use-isomorphic-layout-effect": "^1.1.2"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
"node_modules/reactjs-popup": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/reactjs-popup/-/reactjs-popup-2.0.6.tgz",
@@ -17944,6 +18141,12 @@
"postcss": "^8.2.15"
}
},
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
+ "license": "MIT"
+ },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -18955,6 +19158,20 @@
"requires-port": "^1.0.0"
}
},
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
+ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 78a55d79..076c339a 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -33,10 +33,11 @@
"react-router-dom": "^6.26.2",
"react-router-hash-link": "^2.4.3",
"react-scripts": "^5.0.1",
+ "react-select": "^5.8.1",
"reactjs-popup": "^2.0.6"
},
"scripts": {
- "start": "react-scripts --openssl-legacy-provider start",
+ "start": "react-scripts start",
"build": "react-scripts build",
"tsc": "../node_modules/.bin/tsc --noEmit false",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
@@ -71,4 +72,4 @@
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "2.8.8"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/components/FormElements/FormElements.tsx b/frontend/src/components/FormElements/FormElements.tsx
index 616a287d..1e35d94f 100644
--- a/frontend/src/components/FormElements/FormElements.tsx
+++ b/frontend/src/components/FormElements/FormElements.tsx
@@ -2,7 +2,7 @@ import React, { SelectHTMLAttributes } from 'react';
import cn from 'classnames';
import styles from './formelements.module.css';
import Select, { ActionMeta, Props as SelectProps } from 'react-select';
-import { Control, RegisterOptions, useController } from 'react-hook-form';
+import { Control, RegisterOptions, useController, Path, FieldValues } from 'react-hook-form';
type LabelType = React.DetailedHTMLProps<
React.LabelHTMLAttributes,
@@ -86,25 +86,25 @@ type SelectOption = {
label: string;
};
-type SelectComponentProps = SelectProps & {
- control: Control;
- name: string;
+type SelectComponentProps = SelectProps & {
+ control: Control;
+ name: Path;
datalist: Option[];
className?: string;
- rules?: RegisterOptions;
+ rules?: RegisterOptions;
};
-export const SelectComponent: React.FC = ({
+export const SelectComponent = ({
control,
name,
datalist,
className,
rules,
...rest
-}) => {
+}: SelectComponentProps) => {
const {
field: { onChange, value, ref, ...inputProps },
- } = useController({
+ } = useController({
name,
control,
rules,
@@ -132,4 +132,4 @@ export const SelectComponent: React.FC = ({
{...rest}
/>
);
-};
+};
\ No newline at end of file
diff --git a/frontend/src/components/Modal/RiderModalInfo.tsx b/frontend/src/components/Modal/RiderModalInfo.tsx
index fbf7907d..185ab7bc 100644
--- a/frontend/src/components/Modal/RiderModalInfo.tsx
+++ b/frontend/src/components/Modal/RiderModalInfo.tsx
@@ -1,7 +1,12 @@
import React, { useState } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import cn from 'classnames';
-import { Button, Input, Label } from '../FormElements/FormElements';
+import {
+ Button,
+ Input,
+ Label,
+ SelectComponent,
+} from '../FormElements/FormElements';
import styles from './ridermodal.module.css';
import { ObjectType, Accessibility, Rider } from '../../types/index';
@@ -31,6 +36,7 @@ const RiderModalInfo: React.FC = ({
rider,
}) => {
const {
+ control,
register,
formState: { errors },
handleSubmit,
@@ -181,6 +187,20 @@ const RiderModalInfo: React.FC = ({
)}
+
+
+
+ name="needs"
+ datalist={Object.entries(Accessibility).map(([key, value]) => ({
+ id: key,
+ name: value,
+ }))}
+ isSearchable={true}
+ control={control}
+ isMulti={true}
+ rules={{ required: 'Rider name is required' }}
+ />
+
{errors.driver?.type === 'required' && (
-
- Please select a driver
-
+ Please select a driver
)}
diff --git a/frontend/src/components/RideModal/Pages/RideTimes.tsx b/frontend/src/components/RideModal/Pages/RideTimes.tsx
index dd4e9cae..83ba7a9d 100644
--- a/frontend/src/components/RideModal/Pages/RideTimes.tsx
+++ b/frontend/src/components/RideModal/Pages/RideTimes.tsx
@@ -13,7 +13,6 @@ import {
Button,
Input,
Label,
- SelectComponent,
} from '../../FormElements/FormElements';
import styles from '../ridemodal.module.css';
import { useDate } from '../../../context/date';
@@ -211,13 +210,18 @@ const RideTimesPage: React.FC = ({
Repeats:
-
+
{errors.repeats?.type === 'required' && (
Please enter a time
)}
diff --git a/frontend/src/components/RideModal/Pages/RiderInfo.tsx b/frontend/src/components/RideModal/Pages/RiderInfo.tsx
index cab83d3a..03b80aee 100644
--- a/frontend/src/components/RideModal/Pages/RiderInfo.tsx
+++ b/frontend/src/components/RideModal/Pages/RiderInfo.tsx
@@ -20,7 +20,13 @@ interface FormData {
}
const RiderInfoPage = ({ formData, onBack, onSubmit }: ModalPageProps) => {
- const { control, register, handleSubmit, formState, getValues } = useForm({
+ const {
+ control,
+ register,
+ handleSubmit,
+ formState: { errors },
+ getValues,
+ } = useForm
({
defaultValues: {
name: formData?.rider ?? '',
pickupLoc: formData?.pickupLoc ?? '',
@@ -79,7 +85,7 @@ const RiderInfoPage = ({ formData, onBack, onSubmit }: ModalPageProps) => {
nameToId[name.toLowerCase()] !== undefined,
})}
/> */}
-
name="name"
datalist={Object.entries(nameToId).map(([name, id]) => ({
id,
diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx
index a8e26358..23212786 100644
--- a/frontend/src/components/RideModal/RideModal.tsx
+++ b/frontend/src/components/RideModal/RideModal.tsx
@@ -16,8 +16,54 @@ type RideModalProps = {
editSingle?: boolean;
};
+const getRideData = (ride: Ride | undefined) => {
+ if (ride) {
+ let rideData: ObjectType = {
+ date: format_date(ride.startTime),
+ pickupTime: moment(ride.startTime).format('kk:mm'),
+ dropoffTime: moment(ride.endTime).format('kk:mm'),
+ rider: `${ride.rider.firstName} ${ride.rider.lastName}`,
+ pickupLoc: ride.startLocation.id
+ ? ride.startLocation.name
+ : ride.startLocation.address,
+ dropoffLoc: ride.endLocation.id
+ ? ride.endLocation.name
+ : ride.endLocation.address,
+ };
+ if (ride.recurring) {
+ let repeats;
+ let days;
+ const startDay = moment(ride.startTime).weekday();
+
+ if (ride.recurringDays!.length === 5) {
+ repeats = RepeatValues.Daily;
+ } else if (
+ ride.recurringDays!.length === 1 &&
+ ride.recurringDays![0] === startDay
+ ) {
+ repeats = RepeatValues.Weekly;
+ } else {
+ repeats = RepeatValues.Custom;
+ const numToDay = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
+ days = ride.recurringDays!.reduce((prev, curr) => {
+ return { ...prev, [numToDay[curr]]: '1' };
+ }, {} as ObjectType);
+ }
+
+ rideData = {
+ ...rideData,
+ repeats,
+ days,
+ endDate: format_date(ride.endDate),
+ };
+ }
+ return rideData;
+ }
+ return {};
+};
+
const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => {
- const originalRideData = getRideData();
+ const originalRideData = getRideData(ride);
const [formData, setFormData] = useState(originalRideData);
const [isOpen, setIsOpen] = useState(open !== undefined ? open : false);
const [currentPage, setCurrentPage] = useState(0);
@@ -25,54 +71,6 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => {
const { showToast } = useToast();
const { refreshRides } = useRides();
- // using function instead of const so the function can be hoisted and
- // not get in the way of the state and hooks
- function getRideData() {
- if (ride) {
- let rideData: ObjectType = {
- date: format_date(ride.startTime),
- pickupTime: moment(ride.startTime).format('kk:mm'),
- dropoffTime: moment(ride.endTime).format('kk:mm'),
- rider: `${ride.rider.firstName} ${ride.rider.lastName}`,
- pickupLoc: ride.startLocation.id
- ? ride.startLocation.name
- : ride.startLocation.address,
- dropoffLoc: ride.endLocation.id
- ? ride.endLocation.name
- : ride.endLocation.address,
- };
- if (ride.recurring) {
- let repeats;
- let days;
- const startDay = moment(ride.startTime).weekday();
-
- if (ride.recurringDays!.length === 5) {
- repeats = RepeatValues.Daily;
- } else if (
- ride.recurringDays!.length === 1 &&
- ride.recurringDays![0] === startDay
- ) {
- repeats = RepeatValues.Weekly;
- } else {
- repeats = RepeatValues.Custom;
- const numToDay = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
- days = ride.recurringDays!.reduce((prev, curr) => {
- return { ...prev, [numToDay[curr]]: '1' };
- }, {} as ObjectType);
- }
-
- rideData = {
- ...rideData,
- repeats,
- days,
- endDate: format_date(ride.endDate),
- };
- }
- return rideData;
- }
- return {};
- }
-
const goNextPage = () => setCurrentPage((p) => p + 1);
const goPrevPage = () => setCurrentPage((p) => p - 1);
@@ -100,19 +98,6 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => {
const submitData = () => setIsSubmitted(true);
- /**
- * Converts a ride that repeats into a number array representation used by
- * the internal representation of a ride
- *
- * @param date a string representation of the ride start date
- * @param repeats an enum representing how often this ride repeats: Daily,
- * Weekly, or Custom
- * @param days Used if the ride repeats on custom days. An object that
- * maps days (Mon, Tue, Wed, Thur, Fri) to strings, where the string value is
- * non-empty if the ride repeats on that day
- * @returns a number array containing the days of the week where the ride repeats,
- * with Monday represented as 1, Tuesday represented as 2, etc.
- */
const getRecurringDays = (
date: string,
repeats: RepeatValues,
@@ -203,10 +188,8 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => {
closeModal();
showToast(ride ? 'Ride edited.' : 'Ride added.', ToastStatus.SUCCESS);
}
- }, [closeModal, formData, isSubmitted, ride]);
+ }, [closeModal, formData, isSubmitted, ride, editSingle, refreshRides, showToast]);
- // have to do a ternary operator on the entire modal
- // because otherwise the pages would show up wrongly
return ride ? (
<>
{
>
) : (
<>
- {/* only have a button if this modal is not controlled by a table */}
{!open && }
{
);
};
-export default RideModal;
+export default RideModal;
\ No newline at end of file
diff --git a/frontend/src/components/RideModal/ridemodal.module.css b/frontend/src/components/RideModal/ridemodal.module.css
index 7dc194fa..beb8f9a8 100644
--- a/frontend/src/components/RideModal/ridemodal.module.css
+++ b/frontend/src/components/RideModal/ridemodal.module.css
@@ -1,116 +1,215 @@
+/* General form styles */
.form {
display: flex;
flex-direction: column;
- align-items: center;
-}
-
-.error {
- color: #eb0023;
- font-size: 0.7rem;
+ width: 100%;
+ height: 100%;
}
.inputContainer {
margin-bottom: 1.5rem;
+ width: 100%;
}
-.btnContainer {
- display: flex;
+.error {
+ color: #dc3545;
+ font-size: 0.8rem;
+ margin-top: 0.25rem;
}
-.btnContainer > button {
- margin: 0 0.75rem;
+.label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 600;
+ color: #333;
}
-.rideTime {
+/* Input styles */
+input[type="date"],
+input[type="time"],
+select {
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 1rem;
+ border: 1px solid #ced4da;
+ border-radius: 4px;
+ background-color: #fff;
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+input[type="date"]:focus,
+input[type="time"]:focus,
+select:focus {
+ outline: none;
+ border-color: #80bdff;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+
+/* Styled select */
+select {
+ appearance: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23333' viewBox='0 0 16 16'%3E%3Cpath d='M7.247 11.14L2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right 0.75rem center;
+ background-size: 12px;
+ padding-right: 2.5rem;
+}
+
+/* RideTimes and DriverPage shared styles */
+.rideTime,
+.drivers {
display: grid;
grid-template-columns: repeat(2, 1fr);
- grid-gap: 1rem;
-}
-
-.col1 {
- grid-column: 1;
+ grid-gap: 1.25rem;
}
-.col2 {
- grid-column: 2;
+.col1, .col2 {
+ display: flex;
+ flex-direction: column;
}
.colSpan {
- grid-column: 1/-1;
-}
-
-.select {
- border: none;
- border-radius: 0.25rem;
- font-size: 1rem;
- padding: 0.25rem;
- background-color: #eae9e9;
+ grid-column: 1 / -1;
}
+/* Day selector styles */
.day {
- border-radius: 40%;
- height: 1.25rem;
- width: 1.25rem;
- border: none;
+ border-radius: 50%;
+ height: 2.25rem;
+ width: 2.25rem;
+ border: 2px solid #6c757d;
padding: 0;
cursor: pointer;
- margin: 0 0.125rem;
- background-color: rgba(0, 0, 0, 0.1);
+ margin: 0 0.25rem;
+ background-color: transparent;
+ color: #6c757d;
+ font-weight: 600;
+ transition: all 0.2s ease-in-out;
}
.day:focus {
- box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.5);
+ outline: none;
+ box-shadow: 0 0 0 3px rgba(108, 117, 125, 0.5);
}
.daySelected {
- background-color: black;
+ background-color: #000;
color: white;
+ border-color: #000;
}
+/* DriverPage specific styles */
.drivers {
display: flex;
- flex-wrap: wrap;
- max-width: 30rem;
- justify-content: center;
+ flex-direction: column;
+ max-height: 300px;
+ overflow-y: auto;
+ border: 1px solid #ced4da;
+ border-radius: 4px;
+ background-color: #f8f9fa;
}
.driver {
display: flex;
- flex-direction: column;
align-items: center;
- margin: 0 0.625rem;
+ padding: 1rem;
+ border-bottom: 1px solid #e9ecef;
+ transition: background-color 0.2s ease;
+}
+
+.driver:last-child {
+ border-bottom: none;
+}
+
+.driver:hover {
+ background-color: #e9ecef;
}
.driverLabel {
- margin: 0;
+ flex-grow: 1;
+ margin-left: 1rem;
+ font-size: 1rem;
+ color: #333;
+ cursor: pointer;
}
.driverRadio {
- margin: 0;
+ appearance: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ width: 20px;
+ height: 20px;
+ border: 2px solid #ced4da;
+ border-radius: 50%;
+ outline: none;
+ transition: all 0.2s ease;
+}
+
+.driverRadio:checked {
+ border-color: #000;
+ background-color: #000;
+ box-shadow: inset 0 0 0 4px #fff;
}
.driverRadio:focus {
- outline: 3px solid black;
+ box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.25), inset 0 0 0 4px #fff;
}
-.rider {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- grid-template-rows: repeat(2, 1fr);
- column-gap: 1rem;
- row-gap: 1rem;
+/* Button styles */
+.btnContainer {
+ display: flex;
+ justify-content: space-between;
+ margin-top: auto;
}
-.name {
- grid-column: 1/3;
- grid-row: 1;
+.btnContainer button {
+ padding: 0.75rem 1.5rem;
+ font-size: 1rem;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ background-color: #000;
+ color: #fff;
+ border: none;
}
-.nameInput {
- font-size: 1.5rem;
- width: 100%;
+.btnContainer button:hover {
+ background-color: #333;
}
-.label {
- display: block;
+.btnContainer button[type="button"] {
+ background-color: #fff;
+ color: #000;
+ border: 1px solid #000;
+}
+
+.btnContainer button[type="button"]:hover {
+ background-color: #000;
+ color: #fff;
+}
+
+/* Loading state */
+.loading {
+ text-align: center;
+ color: #6c757d;
+ font-style: italic;
}
+
+/* Responsive adjustments */
+@media (max-width: 500px) {
+ .rideTime,
+ .drivers {
+ grid-template-columns: 1fr;
+ }
+
+ .btnContainer {
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .btnContainer button {
+ width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index c63f577d..7d8a8bea 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1066,9 +1066,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
+ "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
"dev": true,
"funding": [
{
@@ -1086,8 +1086,8 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
+ "caniuse-lite": "^1.0.30001663",
+ "electron-to-chromium": "^1.5.28",
"node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.0"
},
@@ -1128,9 +1128,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001663",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz",
- "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==",
+ "version": "1.0.30001664",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
+ "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
"dev": true,
"funding": [
{
@@ -1345,9 +1345,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.27",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz",
- "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==",
+ "version": "1.5.30",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz",
+ "integrity": "sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA==",
"dev": true,
"license": "ISC"
},
@@ -1627,9 +1627,9 @@
}
},
"node_modules/eslint-module-utils": {
- "version": "2.11.1",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.1.tgz",
- "integrity": "sha512-EwcbfLOhwVMAfatfqLecR2yv3dE5+kQ8kx+Rrt0DvDXEVwW86KQ/xbMDQhtp5l42VXukD5SOF8mQQHbaNtO0CQ==",
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz",
+ "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1726,9 +1726,9 @@
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.36.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz",
- "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==",
+ "version": "7.37.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz",
+ "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4029,9 +4029,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"dev": true,
"funding": [
{
@@ -4049,8 +4049,8 @@
],
"license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
},
"bin": {
"update-browserslist-db": "cli.js"