@navigoo/map-components 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Dashboard.d.ts +1 -0
- package/dist/components/Dashboard.js +2 -8
- package/dist/components/DetourRouteSearch.d.ts +9 -0
- package/dist/components/DetourRouteSearch.js +5 -9
- package/dist/components/RouteSearch.d.ts +9 -0
- package/dist/components/RouteSearch.js +4 -8
- package/dist/components/SearchBar.d.ts +6 -0
- package/dist/components/SearchBar.js +2 -6
- package/dist/components/TransportOptions.d.ts +12 -1
- package/dist/components/TransportOptions.js +3 -7
- package/dist/components/TripType.d.ts +12 -1
- package/dist/components/TripType.js +3 -7
- package/package.json +1 -1
- package/src/components/Dashboard.tsx +52 -116
- package/src/components/DetourRouteSearch.tsx +42 -21
- package/src/components/RouteSearch.tsx +37 -16
- package/src/components/SearchBar.tsx +25 -10
- package/src/components/TransportOptions.tsx +31 -13
- package/src/components/TripType.tsx +31 -12
- package/src/components/styles.module.css +0 -207
- /package/src/{css-module.d.ts → css-modules.d.ts} +0 -0
@@ -11,15 +11,9 @@ const RouteSearch_1 = __importDefault(require("./RouteSearch"));
|
|
11
11
|
const DetourRouteSearch_1 = __importDefault(require("./DetourRouteSearch"));
|
12
12
|
const TransportOptions_1 = __importDefault(require("./TransportOptions"));
|
13
13
|
const TripType_1 = __importDefault(require("./TripType"));
|
14
|
-
const
|
15
|
-
const lucide_react_1 = require("lucide-react");
|
16
|
-
const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking, setRoutes, setSelectedRouteIndex, isTracking, }) => {
|
17
|
-
const [activeSection, setActiveSection] = (0, react_1.useState)(null);
|
14
|
+
const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking, setRoutes, setSelectedRouteIndex, isTracking, className, }) => {
|
18
15
|
const [geoLoading, setGeoLoading] = (0, react_1.useState)(false);
|
19
16
|
const [geoError, setGeoError] = (0, react_1.useState)(null);
|
20
|
-
const toggleSection = (section) => {
|
21
|
-
setActiveSection(activeSection === section ? null : section);
|
22
|
-
};
|
23
17
|
const handleToggleTracking = () => {
|
24
18
|
setIsTracking(!isTracking);
|
25
19
|
if (isTracking) {
|
@@ -47,6 +41,6 @@ const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking
|
|
47
41
|
setGeoLoading(false);
|
48
42
|
}
|
49
43
|
}, [geoLoading, isTracking, setUserLocation, setRoutes, setSelectedRouteIndex]);
|
50
|
-
return ((0, jsx_runtime_1.jsxs)("div", {
|
44
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)("label", { children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: isTracking, onChange: handleToggleTracking }), "Suivi: ", isTracking ? 'Activé' : 'Désactivé'] }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleGeolocation, disabled: geoLoading || isTracking, children: geoLoading ? 'Chargement...' : 'Ma position' }), geoError && (0, jsx_runtime_1.jsx)("div", { children: geoError })] }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(SearchBar_1.default, { apiClient: apiClient, setUserLocation: setUserLocation, setSearchedPlace: setSearchedPlace }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(RouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(DetourRouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] })] }));
|
51
45
|
};
|
52
46
|
exports.default = Dashboard;
|
@@ -5,6 +5,15 @@ interface DetourRouteSearchProps {
|
|
5
5
|
apiClient: ApiClient;
|
6
6
|
setRoutes: (routes: Route[]) => void;
|
7
7
|
setSelectedRouteIndex: (index: number) => void;
|
8
|
+
className?: string;
|
9
|
+
searchGroupClassName?: string;
|
10
|
+
labelClassName?: string;
|
11
|
+
inputClassName?: string;
|
12
|
+
resultsClassName?: string;
|
13
|
+
resultItemClassName?: string;
|
14
|
+
errorClassName?: string;
|
15
|
+
buttonClassName?: string;
|
16
|
+
disabledButtonClassName?: string;
|
8
17
|
}
|
9
18
|
declare const DetourRouteSearch: React.FC<DetourRouteSearchProps>;
|
10
19
|
export default DetourRouteSearch;
|
@@ -1,12 +1,8 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
7
4
|
const react_1 = require("react");
|
8
|
-
const
|
9
|
-
const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
|
5
|
+
const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex, className, searchGroupClassName, labelClassName, inputClassName, resultsClassName, resultItemClassName, errorClassName, buttonClassName, disabledButtonClassName, }) => {
|
10
6
|
const [startQuery, setStartQuery] = (0, react_1.useState)('');
|
11
7
|
const [detourQuery, setDetourQuery] = (0, react_1.useState)('');
|
12
8
|
const [endQuery, setEndQuery] = (0, react_1.useState)('');
|
@@ -105,15 +101,15 @@ const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
|
|
105
101
|
setLoading(false);
|
106
102
|
}
|
107
103
|
};
|
108
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className:
|
104
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: labelClassName, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
|
109
105
|
setStartQuery(e.target.value);
|
110
106
|
handleSearch(e.target.value, setStartResults);
|
111
|
-
}, placeholder: "Point de d\u00E9part", className:
|
107
|
+
}, placeholder: "Point de d\u00E9part", className: inputClassName }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "detour", className: labelClassName, children: "D\u00E9tour" }), (0, jsx_runtime_1.jsx)("input", { id: "detour", type: "text", value: detourQuery, onChange: (e) => {
|
112
108
|
setDetourQuery(e.target.value);
|
113
109
|
handleSearch(e.target.value, setDetourResults);
|
114
|
-
}, placeholder: "Point de d\u00E9tour", className:
|
110
|
+
}, placeholder: "Point de d\u00E9tour", className: inputClassName }), detourResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: detourResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectDetour(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: labelClassName, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
|
115
111
|
setEndQuery(e.target.value);
|
116
112
|
handleSearch(e.target.value, setEndResults);
|
117
|
-
}, placeholder: "Point d'arriv\u00E9e", className:
|
113
|
+
}, placeholder: "Point d'arriv\u00E9e", className: inputClassName }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedDetour || !selectedEnd, className: loading || !selectedStart || !selectedDetour || !selectedEnd ? disabledButtonClassName : buttonClassName, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
|
118
114
|
};
|
119
115
|
exports.default = DetourRouteSearch;
|
@@ -5,6 +5,15 @@ interface RouteSearchProps {
|
|
5
5
|
apiClient: ApiClient;
|
6
6
|
setRoutes: (routes: Route[]) => void;
|
7
7
|
setSelectedRouteIndex: (index: number) => void;
|
8
|
+
className?: string;
|
9
|
+
searchGroupClassName?: string;
|
10
|
+
labelClassName?: string;
|
11
|
+
inputClassName?: string;
|
12
|
+
resultsClassName?: string;
|
13
|
+
resultItemClassName?: string;
|
14
|
+
errorClassName?: string;
|
15
|
+
buttonClassName?: string;
|
16
|
+
disabledButtonClassName?: string;
|
8
17
|
}
|
9
18
|
declare const RouteSearch: React.FC<RouteSearchProps>;
|
10
19
|
export default RouteSearch;
|
@@ -1,12 +1,8 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
7
4
|
const react_1 = require("react");
|
8
|
-
const
|
9
|
-
const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
|
5
|
+
const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex, className, searchGroupClassName, labelClassName, inputClassName, resultsClassName, resultItemClassName, errorClassName, buttonClassName, disabledButtonClassName, }) => {
|
10
6
|
const [startQuery, setStartQuery] = (0, react_1.useState)('');
|
11
7
|
const [endQuery, setEndQuery] = (0, react_1.useState)('');
|
12
8
|
const [startResults, setStartResults] = (0, react_1.useState)([]);
|
@@ -84,12 +80,12 @@ const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
|
|
84
80
|
setLoading(false);
|
85
81
|
}
|
86
82
|
};
|
87
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className:
|
83
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: labelClassName, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
|
88
84
|
setStartQuery(e.target.value);
|
89
85
|
handleSearch(e.target.value, setStartResults);
|
90
|
-
}, placeholder: "Point de d\u00E9part", className:
|
86
|
+
}, placeholder: "Point de d\u00E9part", className: inputClassName }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: labelClassName, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
|
91
87
|
setEndQuery(e.target.value);
|
92
88
|
handleSearch(e.target.value, setEndResults);
|
93
|
-
}, placeholder: "Point d'arriv\u00E9e", className:
|
89
|
+
}, placeholder: "Point d'arriv\u00E9e", className: inputClassName }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedEnd, className: loading || !selectedStart || !selectedEnd ? disabledButtonClassName : buttonClassName, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
|
94
90
|
};
|
95
91
|
exports.default = RouteSearch;
|
@@ -5,6 +5,12 @@ interface SearchBarProps {
|
|
5
5
|
apiClient: ApiClient;
|
6
6
|
setUserLocation: (location: GeolocationResult | null) => void;
|
7
7
|
setSearchedPlace: (place: Place | null) => void;
|
8
|
+
className?: string;
|
9
|
+
inputClassName?: string;
|
10
|
+
buttonClassName?: string;
|
11
|
+
errorClassName?: string;
|
12
|
+
resultsClassName?: string;
|
13
|
+
resultItemClassName?: string;
|
8
14
|
}
|
9
15
|
declare const SearchBar: React.FC<SearchBarProps>;
|
10
16
|
export default SearchBar;
|
@@ -1,12 +1,8 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
7
4
|
const react_1 = require("react");
|
8
|
-
const
|
9
|
-
const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace }) => {
|
5
|
+
const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace, className, inputClassName, buttonClassName, errorClassName, resultsClassName, resultItemClassName, }) => {
|
10
6
|
const [query, setQuery] = (0, react_1.useState)('');
|
11
7
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
12
8
|
const [results, setResults] = (0, react_1.useState)([]);
|
@@ -43,6 +39,6 @@ const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace }) => {
|
|
43
39
|
}
|
44
40
|
setResults([]);
|
45
41
|
};
|
46
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className:
|
42
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "search", children: "Nom du lieu" }), (0, jsx_runtime_1.jsx)("input", { id: "search", type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Rechercher un lieu", className: inputClassName })] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), results.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: results.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelect(place), className: resultItemClassName, children: place.name }, place.id))) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleSearch, disabled: loading || !query, className: buttonClassName, children: loading ? 'Recherche...' : 'Rechercher' })] }));
|
47
43
|
};
|
48
44
|
exports.default = SearchBar;
|
@@ -1,3 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
|
2
|
+
interface TransportOptionsProps {
|
3
|
+
className?: string;
|
4
|
+
headerClassName?: string;
|
5
|
+
titleClassName?: string;
|
6
|
+
toggleButtonClassName?: string;
|
7
|
+
optionsClassName?: string;
|
8
|
+
optionClassName?: string;
|
9
|
+
selectedOptionClassName?: string;
|
10
|
+
iconClassName?: string;
|
11
|
+
nameClassName?: string;
|
12
|
+
}
|
13
|
+
declare const TransportOptions: React.FC<TransportOptionsProps>;
|
3
14
|
export default TransportOptions;
|
@@ -1,12 +1,8 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
7
4
|
const react_1 = require("react");
|
8
|
-
const
|
9
|
-
const TransportOptions = () => {
|
5
|
+
const TransportOptions = ({ className, headerClassName, titleClassName, toggleButtonClassName, optionsClassName, optionClassName, selectedOptionClassName, iconClassName, nameClassName, }) => {
|
10
6
|
const [showOptions, setShowOptions] = (0, react_1.useState)(false);
|
11
7
|
const [selectedTransport, setSelectedTransport] = (0, react_1.useState)('taxi');
|
12
8
|
const transportOptions = [
|
@@ -17,8 +13,8 @@ const TransportOptions = () => {
|
|
17
13
|
(0, react_1.useEffect)(() => {
|
18
14
|
window.dispatchEvent(new CustomEvent('transportChange', { detail: selectedTransport }));
|
19
15
|
}, [selectedTransport]);
|
20
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className:
|
16
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: headerClassName, children: [(0, jsx_runtime_1.jsx)("h3", { className: titleClassName, children: "Moyen de transport" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: toggleButtonClassName, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: optionsClassName, children: transportOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTransport(option.id), className: `${optionClassName} ${selectedTransport === option.id ? selectedOptionClassName : ''}`, style: {
|
21
17
|
backgroundColor: selectedTransport === option.id ? option.color : undefined,
|
22
|
-
}, children: [(0, jsx_runtime_1.jsx)("span", { className:
|
18
|
+
}, children: [(0, jsx_runtime_1.jsx)("span", { className: iconClassName, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: nameClassName, children: option.name })] }, option.id))) }))] }));
|
23
19
|
};
|
24
20
|
exports.default = TransportOptions;
|
@@ -1,3 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
|
2
|
+
interface TripTypeProps {
|
3
|
+
className?: string;
|
4
|
+
headerClassName?: string;
|
5
|
+
titleClassName?: string;
|
6
|
+
toggleButtonClassName?: string;
|
7
|
+
optionsClassName?: string;
|
8
|
+
optionClassName?: string;
|
9
|
+
selectedOptionClassName?: string;
|
10
|
+
iconClassName?: string;
|
11
|
+
nameClassName?: string;
|
12
|
+
}
|
13
|
+
declare const TripType: React.FC<TripTypeProps>;
|
3
14
|
export default TripType;
|
@@ -1,20 +1,16 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
7
4
|
const react_1 = require("react");
|
8
|
-
const
|
9
|
-
const TripType = () => {
|
5
|
+
const TripType = ({ className, headerClassName, titleClassName, toggleButtonClassName, optionsClassName, optionClassName, selectedOptionClassName, iconClassName, nameClassName, }) => {
|
10
6
|
const [showOptions, setShowOptions] = (0, react_1.useState)(false);
|
11
7
|
const [selectedTripType, setSelectedTripType] = (0, react_1.useState)('individuel');
|
12
8
|
const tripTypeOptions = [
|
13
9
|
{ id: 'individuel', name: 'Individuel', icon: '👤', color: '#3498db' },
|
14
10
|
{ id: 'ramassage', name: 'Ramassage', icon: '👥', color: '#9b59b6' },
|
15
11
|
];
|
16
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className:
|
12
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: headerClassName, children: [(0, jsx_runtime_1.jsx)("h3", { className: titleClassName, children: "Type de trajet" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: toggleButtonClassName, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: optionsClassName, children: tripTypeOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTripType(option.id), className: `${optionClassName} ${selectedTripType === option.id ? selectedOptionClassName : ''}`, style: {
|
17
13
|
backgroundColor: selectedTripType === option.id ? option.color : undefined,
|
18
|
-
}, children: [(0, jsx_runtime_1.jsx)("span", { className:
|
14
|
+
}, children: [(0, jsx_runtime_1.jsx)("span", { className: iconClassName, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: nameClassName, children: option.name })] }, option.id))) }))] }));
|
19
15
|
};
|
20
16
|
exports.default = TripType;
|
package/package.json
CHANGED
@@ -6,8 +6,6 @@ import RouteSearch from './RouteSearch';
|
|
6
6
|
import DetourRouteSearch from './DetourRouteSearch';
|
7
7
|
import TransportOptions from './TransportOptions';
|
8
8
|
import TripType from './TripType';
|
9
|
-
import styles from './styles.module.css';
|
10
|
-
import { Footprints, Search, ArrowRight, RefreshCcw, MapPin } from 'lucide-react';
|
11
9
|
import { ApiClient } from '../lib/api';
|
12
10
|
|
13
11
|
interface DashboardProps {
|
@@ -18,6 +16,7 @@ interface DashboardProps {
|
|
18
16
|
setRoutes: (routes: Route[]) => void;
|
19
17
|
setSelectedRouteIndex: (index: number) => void;
|
20
18
|
isTracking: boolean;
|
19
|
+
className?: string; // Allow custom styling
|
21
20
|
}
|
22
21
|
|
23
22
|
const Dashboard: React.FC<DashboardProps> = ({
|
@@ -28,15 +27,11 @@ const Dashboard: React.FC<DashboardProps> = ({
|
|
28
27
|
setRoutes,
|
29
28
|
setSelectedRouteIndex,
|
30
29
|
isTracking,
|
30
|
+
className,
|
31
31
|
}) => {
|
32
|
-
const [activeSection, setActiveSection] = useState<string | null>(null);
|
33
32
|
const [geoLoading, setGeoLoading] = useState(false);
|
34
33
|
const [geoError, setGeoError] = useState<string | null>(null);
|
35
34
|
|
36
|
-
const toggleSection = (section: string) => {
|
37
|
-
setActiveSection(activeSection === section ? null : section);
|
38
|
-
};
|
39
|
-
|
40
35
|
const handleToggleTracking = () => {
|
41
36
|
setIsTracking(!isTracking);
|
42
37
|
if (isTracking) {
|
@@ -65,116 +60,57 @@ const Dashboard: React.FC<DashboardProps> = ({
|
|
65
60
|
}, [geoLoading, isTracking, setUserLocation, setRoutes, setSelectedRouteIndex]);
|
66
61
|
|
67
62
|
return (
|
68
|
-
<div>
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
>
|
81
|
-
<Footprints size={24} color="#000" />
|
82
|
-
</button>
|
83
|
-
<button
|
84
|
-
onClick={() => toggleSection('search')}
|
85
|
-
className={`${styles.sidebarButton} ${activeSection === 'search' ? styles.active : ''}`}
|
86
|
-
title="Recherche de lieu"
|
87
|
-
>
|
88
|
-
<Search size={24} color="#000" />
|
89
|
-
</button>
|
90
|
-
<button
|
91
|
-
onClick={() => toggleSection('route')}
|
92
|
-
className={`${styles.sidebarButton} ${activeSection === 'route' ? styles.active : ''}`}
|
93
|
-
title="Tracé d'itinéraire"
|
94
|
-
>
|
95
|
-
<ArrowRight size={24} color="#000" />
|
96
|
-
</button>
|
97
|
-
<button
|
98
|
-
onClick={() => toggleSection('routeWithDetour')}
|
99
|
-
className={`${styles.sidebarButton} ${activeSection === 'routeWithDetour' ? styles.active : ''}`}
|
100
|
-
title="Tracé d'itinéraire avec détour"
|
101
|
-
>
|
102
|
-
<RefreshCcw size={24} color="#000" />
|
103
|
-
</button>
|
104
|
-
</div>
|
105
|
-
<div className={`${styles.contentPanel} ${activeSection ? styles.open : ''}`}>
|
106
|
-
{activeSection === 'geolocation' && (
|
107
|
-
<div className={styles.sectionContainer}>
|
108
|
-
<h2 className={styles.sectionTitle}>
|
109
|
-
<span className={styles.titleAccent}>Géo</span>localisation
|
110
|
-
</h2>
|
111
|
-
<div className={styles.toggleContainer}>
|
112
|
-
<label className={styles.switch}>
|
113
|
-
<input type="checkbox" checked={isTracking} onChange={handleToggleTracking} />
|
114
|
-
<span className={styles.slider}></span>
|
115
|
-
</label>
|
116
|
-
<span className={styles.toggleLabel}>
|
117
|
-
Suivi: {isTracking ? 'Activé' : 'Désactivé'}
|
118
|
-
</span>
|
119
|
-
</div>
|
120
|
-
<button
|
121
|
-
onClick={handleGeolocation}
|
122
|
-
className={styles.locationButton}
|
123
|
-
disabled={geoLoading || isTracking}
|
124
|
-
>
|
125
|
-
{geoLoading ? (
|
126
|
-
'Chargement...'
|
127
|
-
) : (
|
128
|
-
<>
|
129
|
-
<MapPin size={18} color="#000" style={{ marginRight: '8px' }} />
|
130
|
-
Ma position
|
131
|
-
</>
|
132
|
-
)}
|
133
|
-
</button>
|
134
|
-
{geoError && <div className={styles.error}>{geoError}</div>}
|
135
|
-
</div>
|
136
|
-
)}
|
137
|
-
{activeSection === 'search' && (
|
138
|
-
<div className={styles.sectionContainer}>
|
139
|
-
<h2 className={styles.sectionTitle}>
|
140
|
-
<span className={styles.titleAccent}>Re</span>cherche
|
141
|
-
</h2>
|
142
|
-
<SearchBar
|
143
|
-
apiClient={apiClient}
|
144
|
-
setUserLocation={setUserLocation}
|
145
|
-
setSearchedPlace={setSearchedPlace}
|
146
|
-
/>
|
147
|
-
</div>
|
148
|
-
)}
|
149
|
-
{activeSection === 'route' && (
|
150
|
-
<div className={styles.sectionContainer}>
|
151
|
-
<h2 className={styles.sectionTitle}>
|
152
|
-
<span className={styles.titleAccent}>Itiné</span>raire
|
153
|
-
</h2>
|
154
|
-
<RouteSearch
|
155
|
-
apiClient={apiClient}
|
156
|
-
setRoutes={setRoutes}
|
157
|
-
setSelectedRouteIndex={setSelectedRouteIndex}
|
158
|
-
/>
|
159
|
-
<TransportOptions />
|
160
|
-
<TripType />
|
161
|
-
</div>
|
162
|
-
)}
|
163
|
-
{activeSection === 'routeWithDetour' && (
|
164
|
-
<div className={styles.sectionContainer}>
|
165
|
-
<h2 className={styles.sectionTitle}>
|
166
|
-
<span className={styles.titleAccent}>Itiné</span>raire avec détour
|
167
|
-
</h2>
|
168
|
-
<DetourRouteSearch
|
169
|
-
apiClient={apiClient}
|
170
|
-
setRoutes={setRoutes}
|
171
|
-
setSelectedRouteIndex={setSelectedRouteIndex}
|
172
|
-
/>
|
173
|
-
<TransportOptions />
|
174
|
-
<TripType />
|
175
|
-
</div>
|
176
|
-
)}
|
63
|
+
<div className={className}>
|
64
|
+
{/* Geolocation Section */}
|
65
|
+
<div>
|
66
|
+
<div>
|
67
|
+
<label>
|
68
|
+
<input
|
69
|
+
type="checkbox"
|
70
|
+
checked={isTracking}
|
71
|
+
onChange={handleToggleTracking}
|
72
|
+
/>
|
73
|
+
Suivi: {isTracking ? 'Activé' : 'Désactivé'}
|
74
|
+
</label>
|
177
75
|
</div>
|
76
|
+
<button
|
77
|
+
onClick={handleGeolocation}
|
78
|
+
disabled={geoLoading || isTracking}
|
79
|
+
>
|
80
|
+
{geoLoading ? 'Chargement...' : 'Ma position'}
|
81
|
+
</button>
|
82
|
+
{geoError && <div>{geoError}</div>}
|
83
|
+
</div>
|
84
|
+
|
85
|
+
{/* Search Section */}
|
86
|
+
<div>
|
87
|
+
<SearchBar
|
88
|
+
apiClient={apiClient}
|
89
|
+
setUserLocation={setUserLocation}
|
90
|
+
setSearchedPlace={setSearchedPlace}
|
91
|
+
/>
|
92
|
+
</div>
|
93
|
+
|
94
|
+
{/* Route Search Section */}
|
95
|
+
<div>
|
96
|
+
<RouteSearch
|
97
|
+
apiClient={apiClient}
|
98
|
+
setRoutes={setRoutes}
|
99
|
+
setSelectedRouteIndex={setSelectedRouteIndex}
|
100
|
+
/>
|
101
|
+
<TransportOptions />
|
102
|
+
<TripType />
|
103
|
+
</div>
|
104
|
+
|
105
|
+
{/* Detour Route Search Section */}
|
106
|
+
<div>
|
107
|
+
<DetourRouteSearch
|
108
|
+
apiClient={apiClient}
|
109
|
+
setRoutes={setRoutes}
|
110
|
+
setSelectedRouteIndex={setSelectedRouteIndex}
|
111
|
+
/>
|
112
|
+
<TransportOptions />
|
113
|
+
<TripType />
|
178
114
|
</div>
|
179
115
|
</div>
|
180
116
|
);
|
@@ -1,15 +1,36 @@
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
1
|
+
import React, { useState, useEffect, ReactNode } from 'react';
|
2
2
|
import { Place, Route } from '../lib/type';
|
3
3
|
import { ApiClient } from '../lib/api';
|
4
|
-
import styles from './styles.module.css';
|
5
4
|
|
6
5
|
interface DetourRouteSearchProps {
|
7
6
|
apiClient: ApiClient;
|
8
7
|
setRoutes: (routes: Route[]) => void;
|
9
8
|
setSelectedRouteIndex: (index: number) => void;
|
9
|
+
className?: string;
|
10
|
+
searchGroupClassName?: string;
|
11
|
+
labelClassName?: string;
|
12
|
+
inputClassName?: string;
|
13
|
+
resultsClassName?: string;
|
14
|
+
resultItemClassName?: string;
|
15
|
+
errorClassName?: string;
|
16
|
+
buttonClassName?: string;
|
17
|
+
disabledButtonClassName?: string;
|
10
18
|
}
|
11
19
|
|
12
|
-
const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({
|
20
|
+
const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({
|
21
|
+
apiClient,
|
22
|
+
setRoutes,
|
23
|
+
setSelectedRouteIndex,
|
24
|
+
className,
|
25
|
+
searchGroupClassName,
|
26
|
+
labelClassName,
|
27
|
+
inputClassName,
|
28
|
+
resultsClassName,
|
29
|
+
resultItemClassName,
|
30
|
+
errorClassName,
|
31
|
+
buttonClassName,
|
32
|
+
disabledButtonClassName,
|
33
|
+
}) => {
|
13
34
|
const [startQuery, setStartQuery] = useState('');
|
14
35
|
const [detourQuery, setDetourQuery] = useState('');
|
15
36
|
const [endQuery, setEndQuery] = useState('');
|
@@ -120,9 +141,9 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
120
141
|
};
|
121
142
|
|
122
143
|
return (
|
123
|
-
<div className={
|
124
|
-
<div className={
|
125
|
-
<label htmlFor="start" className={
|
144
|
+
<div className={className}>
|
145
|
+
<div className={searchGroupClassName}>
|
146
|
+
<label htmlFor="start" className={labelClassName}>Départ</label>
|
126
147
|
<input
|
127
148
|
id="start"
|
128
149
|
type="text"
|
@@ -132,15 +153,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
132
153
|
handleSearch(e.target.value, setStartResults);
|
133
154
|
}}
|
134
155
|
placeholder="Point de départ"
|
135
|
-
className={
|
156
|
+
className={inputClassName}
|
136
157
|
/>
|
137
158
|
{startResults.length > 0 && (
|
138
|
-
<ul className={
|
159
|
+
<ul className={resultsClassName}>
|
139
160
|
{startResults.map((place) => (
|
140
161
|
<li
|
141
162
|
key={place.id}
|
142
163
|
onClick={() => handleSelectStart(place)}
|
143
|
-
className={
|
164
|
+
className={resultItemClassName}
|
144
165
|
>
|
145
166
|
{place.name}
|
146
167
|
</li>
|
@@ -148,8 +169,8 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
148
169
|
</ul>
|
149
170
|
)}
|
150
171
|
</div>
|
151
|
-
<div className={
|
152
|
-
<label htmlFor="detour" className={
|
172
|
+
<div className={searchGroupClassName}>
|
173
|
+
<label htmlFor="detour" className={labelClassName}>Détour</label>
|
153
174
|
<input
|
154
175
|
id="detour"
|
155
176
|
type="text"
|
@@ -159,15 +180,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
159
180
|
handleSearch(e.target.value, setDetourResults);
|
160
181
|
}}
|
161
182
|
placeholder="Point de détour"
|
162
|
-
className={
|
183
|
+
className={inputClassName}
|
163
184
|
/>
|
164
185
|
{detourResults.length > 0 && (
|
165
|
-
<ul className={
|
186
|
+
<ul className={resultsClassName}>
|
166
187
|
{detourResults.map((place) => (
|
167
188
|
<li
|
168
189
|
key={place.id}
|
169
190
|
onClick={() => handleSelectDetour(place)}
|
170
|
-
className={
|
191
|
+
className={resultItemClassName}
|
171
192
|
>
|
172
193
|
{place.name}
|
173
194
|
</li>
|
@@ -175,8 +196,8 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
175
196
|
</ul>
|
176
197
|
)}
|
177
198
|
</div>
|
178
|
-
<div className={
|
179
|
-
<label htmlFor="end" className={
|
199
|
+
<div className={searchGroupClassName}>
|
200
|
+
<label htmlFor="end" className={labelClassName}>Destination</label>
|
180
201
|
<input
|
181
202
|
id="end"
|
182
203
|
type="text"
|
@@ -186,15 +207,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
186
207
|
handleSearch(e.target.value, setEndResults);
|
187
208
|
}}
|
188
209
|
placeholder="Point d'arrivée"
|
189
|
-
className={
|
210
|
+
className={inputClassName}
|
190
211
|
/>
|
191
212
|
{endResults.length > 0 && (
|
192
|
-
<ul className={
|
213
|
+
<ul className={resultsClassName}>
|
193
214
|
{endResults.map((place) => (
|
194
215
|
<li
|
195
216
|
key={place.id}
|
196
217
|
onClick={() => handleSelectEnd(place)}
|
197
|
-
className={
|
218
|
+
className={resultItemClassName}
|
198
219
|
>
|
199
220
|
{place.name}
|
200
221
|
</li>
|
@@ -202,11 +223,11 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
|
|
202
223
|
</ul>
|
203
224
|
)}
|
204
225
|
</div>
|
205
|
-
{error && <div className={
|
226
|
+
{error && <div className={errorClassName}>{error}</div>}
|
206
227
|
<button
|
207
228
|
onClick={handleCalculateRoute}
|
208
229
|
disabled={loading || !selectedStart || !selectedDetour || !selectedEnd}
|
209
|
-
className={
|
230
|
+
className={loading || !selectedStart || !selectedDetour || !selectedEnd ? disabledButtonClassName : buttonClassName}
|
210
231
|
>
|
211
232
|
{loading ? 'Calcul...' : 'Calculer l\'itinéraire'}
|
212
233
|
</button>
|
@@ -1,15 +1,36 @@
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
2
|
-
import { Place, Route
|
2
|
+
import { Place, Route } from '../lib/type';
|
3
3
|
import { ApiClient } from '../lib/api';
|
4
|
-
import styles from './styles.module.css';
|
5
4
|
|
6
5
|
interface RouteSearchProps {
|
7
6
|
apiClient: ApiClient;
|
8
7
|
setRoutes: (routes: Route[]) => void;
|
9
8
|
setSelectedRouteIndex: (index: number) => void;
|
9
|
+
className?: string;
|
10
|
+
searchGroupClassName?: string;
|
11
|
+
labelClassName?: string;
|
12
|
+
inputClassName?: string;
|
13
|
+
resultsClassName?: string;
|
14
|
+
resultItemClassName?: string;
|
15
|
+
errorClassName?: string;
|
16
|
+
buttonClassName?: string;
|
17
|
+
disabledButtonClassName?: string;
|
10
18
|
}
|
11
19
|
|
12
|
-
const RouteSearch: React.FC<RouteSearchProps> = ({
|
20
|
+
const RouteSearch: React.FC<RouteSearchProps> = ({
|
21
|
+
apiClient,
|
22
|
+
setRoutes,
|
23
|
+
setSelectedRouteIndex,
|
24
|
+
className,
|
25
|
+
searchGroupClassName,
|
26
|
+
labelClassName,
|
27
|
+
inputClassName,
|
28
|
+
resultsClassName,
|
29
|
+
resultItemClassName,
|
30
|
+
errorClassName,
|
31
|
+
buttonClassName,
|
32
|
+
disabledButtonClassName,
|
33
|
+
}) => {
|
13
34
|
const [startQuery, setStartQuery] = useState('');
|
14
35
|
const [endQuery, setEndQuery] = useState('');
|
15
36
|
const [startResults, setStartResults] = useState<Place[]>([]);
|
@@ -93,9 +114,9 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
|
|
93
114
|
};
|
94
115
|
|
95
116
|
return (
|
96
|
-
<div className={
|
97
|
-
<div className={
|
98
|
-
<label htmlFor="start" className={
|
117
|
+
<div className={className}>
|
118
|
+
<div className={searchGroupClassName}>
|
119
|
+
<label htmlFor="start" className={labelClassName}>Départ</label>
|
99
120
|
<input
|
100
121
|
id="start"
|
101
122
|
type="text"
|
@@ -105,15 +126,15 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
|
|
105
126
|
handleSearch(e.target.value, setStartResults);
|
106
127
|
}}
|
107
128
|
placeholder="Point de départ"
|
108
|
-
className={
|
129
|
+
className={inputClassName}
|
109
130
|
/>
|
110
131
|
{startResults.length > 0 && (
|
111
|
-
<ul className={
|
132
|
+
<ul className={resultsClassName}>
|
112
133
|
{startResults.map((place) => (
|
113
134
|
<li
|
114
135
|
key={place.id}
|
115
136
|
onClick={() => handleSelectStart(place)}
|
116
|
-
className={
|
137
|
+
className={resultItemClassName}
|
117
138
|
>
|
118
139
|
{place.name}
|
119
140
|
</li>
|
@@ -121,8 +142,8 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
|
|
121
142
|
</ul>
|
122
143
|
)}
|
123
144
|
</div>
|
124
|
-
<div className={
|
125
|
-
<label htmlFor="end" className={
|
145
|
+
<div className={searchGroupClassName}>
|
146
|
+
<label htmlFor="end" className={labelClassName}>Destination</label>
|
126
147
|
<input
|
127
148
|
id="end"
|
128
149
|
type="text"
|
@@ -132,15 +153,15 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
|
|
132
153
|
handleSearch(e.target.value, setEndResults);
|
133
154
|
}}
|
134
155
|
placeholder="Point d'arrivée"
|
135
|
-
className={
|
156
|
+
className={inputClassName}
|
136
157
|
/>
|
137
158
|
{endResults.length > 0 && (
|
138
|
-
<ul className={
|
159
|
+
<ul className={resultsClassName}>
|
139
160
|
{endResults.map((place) => (
|
140
161
|
<li
|
141
162
|
key={place.id}
|
142
163
|
onClick={() => handleSelectEnd(place)}
|
143
|
-
className={
|
164
|
+
className={resultItemClassName}
|
144
165
|
>
|
145
166
|
{place.name}
|
146
167
|
</li>
|
@@ -148,11 +169,11 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
|
|
148
169
|
</ul>
|
149
170
|
)}
|
150
171
|
</div>
|
151
|
-
{error && <div className={
|
172
|
+
{error && <div className={errorClassName}>{error}</div>}
|
152
173
|
<button
|
153
174
|
onClick={handleCalculateRoute}
|
154
175
|
disabled={loading || !selectedStart || !selectedEnd}
|
155
|
-
className={
|
176
|
+
className={loading || !selectedStart || !selectedEnd ? disabledButtonClassName : buttonClassName}
|
156
177
|
>
|
157
178
|
{loading ? 'Calcul...' : 'Calculer l\'itinéraire'}
|
158
179
|
</button>
|
@@ -1,15 +1,30 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
2
|
import { Place, GeolocationResult } from '../lib/type';
|
3
3
|
import { ApiClient } from '../lib/api';
|
4
|
-
import styles from './styles.module.css';
|
5
4
|
|
6
5
|
interface SearchBarProps {
|
7
6
|
apiClient: ApiClient;
|
8
7
|
setUserLocation: (location: GeolocationResult | null) => void;
|
9
8
|
setSearchedPlace: (place: Place | null) => void;
|
9
|
+
className?: string;
|
10
|
+
inputClassName?: string;
|
11
|
+
buttonClassName?: string;
|
12
|
+
errorClassName?: string;
|
13
|
+
resultsClassName?: string;
|
14
|
+
resultItemClassName?: string;
|
10
15
|
}
|
11
16
|
|
12
|
-
const SearchBar: React.FC<SearchBarProps> = ({
|
17
|
+
const SearchBar: React.FC<SearchBarProps> = ({
|
18
|
+
apiClient,
|
19
|
+
setUserLocation,
|
20
|
+
setSearchedPlace,
|
21
|
+
className,
|
22
|
+
inputClassName,
|
23
|
+
buttonClassName,
|
24
|
+
errorClassName,
|
25
|
+
resultsClassName,
|
26
|
+
resultItemClassName,
|
27
|
+
}) => {
|
13
28
|
const [query, setQuery] = useState('');
|
14
29
|
const [loading, setLoading] = useState(false);
|
15
30
|
const [results, setResults] = useState<Place[]>([]);
|
@@ -47,26 +62,26 @@ const SearchBar: React.FC<SearchBarProps> = ({ apiClient, setUserLocation, setSe
|
|
47
62
|
};
|
48
63
|
|
49
64
|
return (
|
50
|
-
<div className={
|
51
|
-
<div
|
52
|
-
<label htmlFor="search"
|
65
|
+
<div className={className}>
|
66
|
+
<div>
|
67
|
+
<label htmlFor="search">Nom du lieu</label>
|
53
68
|
<input
|
54
69
|
id="search"
|
55
70
|
type="text"
|
56
71
|
value={query}
|
57
72
|
onChange={(e) => setQuery(e.target.value)}
|
58
73
|
placeholder="Rechercher un lieu"
|
59
|
-
className={
|
74
|
+
className={inputClassName}
|
60
75
|
/>
|
61
76
|
</div>
|
62
|
-
{error && <div className={
|
77
|
+
{error && <div className={errorClassName}>{error}</div>}
|
63
78
|
{results.length > 0 && (
|
64
|
-
<ul className={
|
79
|
+
<ul className={resultsClassName}>
|
65
80
|
{results.map((place) => (
|
66
81
|
<li
|
67
82
|
key={place.id}
|
68
83
|
onClick={() => handleSelect(place)}
|
69
|
-
className={
|
84
|
+
className={resultItemClassName}
|
70
85
|
>
|
71
86
|
{place.name}
|
72
87
|
</li>
|
@@ -76,7 +91,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ apiClient, setUserLocation, setSe
|
|
76
91
|
<button
|
77
92
|
onClick={handleSearch}
|
78
93
|
disabled={loading || !query}
|
79
|
-
className={
|
94
|
+
className={buttonClassName}
|
80
95
|
>
|
81
96
|
{loading ? 'Recherche...' : 'Rechercher'}
|
82
97
|
</button>
|
@@ -1,7 +1,28 @@
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
2
|
-
import styles from './styles.module.css';
|
3
2
|
|
4
|
-
|
3
|
+
interface TransportOptionsProps {
|
4
|
+
className?: string;
|
5
|
+
headerClassName?: string;
|
6
|
+
titleClassName?: string;
|
7
|
+
toggleButtonClassName?: string;
|
8
|
+
optionsClassName?: string;
|
9
|
+
optionClassName?: string;
|
10
|
+
selectedOptionClassName?: string;
|
11
|
+
iconClassName?: string;
|
12
|
+
nameClassName?: string;
|
13
|
+
}
|
14
|
+
|
15
|
+
const TransportOptions: React.FC<TransportOptionsProps> = ({
|
16
|
+
className,
|
17
|
+
headerClassName,
|
18
|
+
titleClassName,
|
19
|
+
toggleButtonClassName,
|
20
|
+
optionsClassName,
|
21
|
+
optionClassName,
|
22
|
+
selectedOptionClassName,
|
23
|
+
iconClassName,
|
24
|
+
nameClassName,
|
25
|
+
}) => {
|
5
26
|
const [showOptions, setShowOptions] = useState(false);
|
6
27
|
const [selectedTransport, setSelectedTransport] = useState('taxi');
|
7
28
|
|
@@ -16,37 +37,34 @@ const TransportOptions: React.FC = () => {
|
|
16
37
|
}, [selectedTransport]);
|
17
38
|
|
18
39
|
return (
|
19
|
-
<div className={
|
20
|
-
<div className={
|
21
|
-
<h3 className={
|
40
|
+
<div className={className}>
|
41
|
+
<div className={headerClassName}>
|
42
|
+
<h3 className={titleClassName}>Moyen de transport</h3>
|
22
43
|
<button
|
23
44
|
onClick={() => setShowOptions(!showOptions)}
|
24
|
-
className={
|
45
|
+
className={toggleButtonClassName}
|
25
46
|
>
|
26
47
|
{showOptions ? 'Réduire' : 'Options'}
|
27
48
|
</button>
|
28
49
|
</div>
|
29
50
|
{showOptions && (
|
30
|
-
<div className={
|
51
|
+
<div className={optionsClassName}>
|
31
52
|
{transportOptions.map((option) => (
|
32
53
|
<button
|
33
54
|
key={option.id}
|
34
55
|
onClick={() => setSelectedTransport(option.id)}
|
35
|
-
className={`${
|
36
|
-
selectedTransport === option.id ? styles.selected : ''
|
37
|
-
}`}
|
56
|
+
className={`${optionClassName} ${selectedTransport === option.id ? selectedOptionClassName : ''}`}
|
38
57
|
style={{
|
39
58
|
backgroundColor: selectedTransport === option.id ? option.color : undefined,
|
40
59
|
}}
|
41
60
|
>
|
42
|
-
<span className={
|
43
|
-
<span className={
|
61
|
+
<span className={iconClassName}>{option.icon}</span>
|
62
|
+
<span className={nameClassName}>{option.name}</span>
|
44
63
|
</button>
|
45
64
|
))}
|
46
65
|
</div>
|
47
66
|
)}
|
48
67
|
</div>
|
49
|
-
|
50
68
|
);
|
51
69
|
};
|
52
70
|
|
@@ -1,7 +1,28 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
|
-
import styles from './styles.module.css';
|
3
2
|
|
4
|
-
|
3
|
+
interface TripTypeProps {
|
4
|
+
className?: string;
|
5
|
+
headerClassName?: string;
|
6
|
+
titleClassName?: string;
|
7
|
+
toggleButtonClassName?: string;
|
8
|
+
optionsClassName?: string;
|
9
|
+
optionClassName?: string;
|
10
|
+
selectedOptionClassName?: string;
|
11
|
+
iconClassName?: string;
|
12
|
+
nameClassName?: string;
|
13
|
+
}
|
14
|
+
|
15
|
+
const TripType: React.FC<TripTypeProps> = ({
|
16
|
+
className,
|
17
|
+
headerClassName,
|
18
|
+
titleClassName,
|
19
|
+
toggleButtonClassName,
|
20
|
+
optionsClassName,
|
21
|
+
optionClassName,
|
22
|
+
selectedOptionClassName,
|
23
|
+
iconClassName,
|
24
|
+
nameClassName,
|
25
|
+
}) => {
|
5
26
|
const [showOptions, setShowOptions] = useState(false);
|
6
27
|
const [selectedTripType, setSelectedTripType] = useState('individuel');
|
7
28
|
|
@@ -11,31 +32,29 @@ const TripType: React.FC = () => {
|
|
11
32
|
];
|
12
33
|
|
13
34
|
return (
|
14
|
-
<div className={
|
15
|
-
<div className={
|
16
|
-
<h3 className={
|
35
|
+
<div className={className}>
|
36
|
+
<div className={headerClassName}>
|
37
|
+
<h3 className={titleClassName}>Type de trajet</h3>
|
17
38
|
<button
|
18
39
|
onClick={() => setShowOptions(!showOptions)}
|
19
|
-
className={
|
40
|
+
className={toggleButtonClassName}
|
20
41
|
>
|
21
42
|
{showOptions ? 'Réduire' : 'Options'}
|
22
43
|
</button>
|
23
44
|
</div>
|
24
45
|
{showOptions && (
|
25
|
-
<div className={
|
46
|
+
<div className={optionsClassName}>
|
26
47
|
{tripTypeOptions.map((option) => (
|
27
48
|
<button
|
28
49
|
key={option.id}
|
29
50
|
onClick={() => setSelectedTripType(option.id)}
|
30
|
-
className={`${
|
31
|
-
selectedTripType === option.id ? styles.selected : ''
|
32
|
-
}`}
|
51
|
+
className={`${optionClassName} ${selectedTripType === option.id ? selectedOptionClassName : ''}`}
|
33
52
|
style={{
|
34
53
|
backgroundColor: selectedTripType === option.id ? option.color : undefined,
|
35
54
|
}}
|
36
55
|
>
|
37
|
-
<span className={
|
38
|
-
<span className={
|
56
|
+
<span className={iconClassName}>{option.icon}</span>
|
57
|
+
<span className={nameClassName}>{option.name}</span>
|
39
58
|
</button>
|
40
59
|
))}
|
41
60
|
</div>
|
@@ -1,207 +0,0 @@
|
|
1
|
-
.header {
|
2
|
-
background-color: #fff;
|
3
|
-
padding: 10px 20px;
|
4
|
-
border-bottom: 1px solid #ddd;
|
5
|
-
}
|
6
|
-
.headerTitle {
|
7
|
-
font-size: 24px;
|
8
|
-
font-weight: bold;
|
9
|
-
}
|
10
|
-
.titleAccent {
|
11
|
-
color: #007bff;
|
12
|
-
}
|
13
|
-
.mainContainer {
|
14
|
-
display: flex;
|
15
|
-
}
|
16
|
-
.sidebar {
|
17
|
-
width: 60px;
|
18
|
-
background-color: #f4f4f4;
|
19
|
-
display: flex;
|
20
|
-
flex-direction: column;
|
21
|
-
align-items: center;
|
22
|
-
padding-top: 20px;
|
23
|
-
}
|
24
|
-
.sidebarButton {
|
25
|
-
background: none;
|
26
|
-
border: none;
|
27
|
-
padding: 10px;
|
28
|
-
cursor: pointer;
|
29
|
-
margin-bottom: 20px;
|
30
|
-
}
|
31
|
-
.sidebarButton.active {
|
32
|
-
background-color: #007bff;
|
33
|
-
border-radius: 5px;
|
34
|
-
}
|
35
|
-
.contentPanel {
|
36
|
-
flex: 1;
|
37
|
-
padding: 20px;
|
38
|
-
transition: all 0.3s;
|
39
|
-
}
|
40
|
-
.contentPanel.open {
|
41
|
-
transform: translateX(0);
|
42
|
-
}
|
43
|
-
.sectionContainer {
|
44
|
-
background-color: #fff;
|
45
|
-
padding: 20px;
|
46
|
-
border-radius: 8px;
|
47
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
48
|
-
}
|
49
|
-
.sectionTitle {
|
50
|
-
font-size: 20px;
|
51
|
-
margin-bottom: 20px;
|
52
|
-
}
|
53
|
-
.toggleContainer {
|
54
|
-
display: flex;
|
55
|
-
align-items: center;
|
56
|
-
margin-bottom: 20px;
|
57
|
-
}
|
58
|
-
.switch {
|
59
|
-
position: relative;
|
60
|
-
display: inline-block;
|
61
|
-
width: 40px;
|
62
|
-
height: 20px;
|
63
|
-
}
|
64
|
-
.switch input {
|
65
|
-
opacity: 0;
|
66
|
-
width: 0;
|
67
|
-
height: 0;
|
68
|
-
}
|
69
|
-
.slider {
|
70
|
-
position: absolute;
|
71
|
-
cursor: pointer;
|
72
|
-
top: 0;
|
73
|
-
left: 0;
|
74
|
-
right: 0;
|
75
|
-
bottom: 0;
|
76
|
-
background-color: #ccc;
|
77
|
-
border-radius: 20px;
|
78
|
-
transition: 0.4s;
|
79
|
-
}
|
80
|
-
.slider:before {
|
81
|
-
position: absolute;
|
82
|
-
content: '';
|
83
|
-
height: 16px;
|
84
|
-
width: 16px;
|
85
|
-
left: 2px;
|
86
|
-
bottom: 2px;
|
87
|
-
background-color: white;
|
88
|
-
border-radius: 50%;
|
89
|
-
transition: 0.4s;
|
90
|
-
}
|
91
|
-
.switch input:checked + .slider {
|
92
|
-
background-color: #007bff;
|
93
|
-
}
|
94
|
-
.switch input:checked + .slider:before {
|
95
|
-
transform: translateX(20px);
|
96
|
-
}
|
97
|
-
.toggleLabel {
|
98
|
-
margin-left: 10px;
|
99
|
-
}
|
100
|
-
.locationButton {
|
101
|
-
display: flex;
|
102
|
-
align-items: center;
|
103
|
-
padding: 10px 20px;
|
104
|
-
background-color: #007bff;
|
105
|
-
color: white;
|
106
|
-
border: none;
|
107
|
-
border-radius: 4px;
|
108
|
-
cursor: pointer;
|
109
|
-
}
|
110
|
-
.locationButton:disabled {
|
111
|
-
background-color: #ccc;
|
112
|
-
cursor: not-allowed;
|
113
|
-
}
|
114
|
-
.error {
|
115
|
-
color: red;
|
116
|
-
margin: 10px 0;
|
117
|
-
}
|
118
|
-
.searchSection {
|
119
|
-
padding: 20px;
|
120
|
-
}
|
121
|
-
.searchGroup {
|
122
|
-
margin-bottom: 15px;
|
123
|
-
}
|
124
|
-
.label {
|
125
|
-
display: block;
|
126
|
-
font-weight: bold;
|
127
|
-
margin-bottom: 5px;
|
128
|
-
}
|
129
|
-
.searchInput {
|
130
|
-
width: 100%;
|
131
|
-
padding: 8px;
|
132
|
-
border: 1px solid #ccc;
|
133
|
-
border-radius: 4px;
|
134
|
-
}
|
135
|
-
.searchResults {
|
136
|
-
list-style: none;
|
137
|
-
padding: 0;
|
138
|
-
margin: 5px 0;
|
139
|
-
border: 1px solid #ccc;
|
140
|
-
max-height: 200px;
|
141
|
-
overflow-y: auto;
|
142
|
-
}
|
143
|
-
.routeSearchSection {
|
144
|
-
padding: 20px;
|
145
|
-
}
|
146
|
-
.route-search {
|
147
|
-
margin-bottom: 20px;
|
148
|
-
}
|
149
|
-
.searchResultItem {
|
150
|
-
padding: 8px;
|
151
|
-
cursor: pointer;
|
152
|
-
}
|
153
|
-
.searchResultItem:hover {
|
154
|
-
background-color: #f0f0f0;
|
155
|
-
}
|
156
|
-
.searchButton {
|
157
|
-
padding: 10px 20px;
|
158
|
-
background-color: #007bff;
|
159
|
-
color: white;
|
160
|
-
border: none;
|
161
|
-
border-radius: 4px;
|
162
|
-
cursor: pointer;
|
163
|
-
}
|
164
|
-
.searchButton.disabled {
|
165
|
-
background-color: #ccc;
|
166
|
-
cursor: not-allowed;
|
167
|
-
}
|
168
|
-
.optionsSection {
|
169
|
-
margin-top: 20px;
|
170
|
-
}
|
171
|
-
.optionsHeader {
|
172
|
-
display: flex;
|
173
|
-
justify-content: space-between;
|
174
|
-
align-items: center;
|
175
|
-
}
|
176
|
-
.optionsTitle {
|
177
|
-
font-size: 16px;
|
178
|
-
font-weight: bold;
|
179
|
-
}
|
180
|
-
.toggleButton {
|
181
|
-
background: none;
|
182
|
-
border: none;
|
183
|
-
color: #007bff;
|
184
|
-
cursor: pointer;
|
185
|
-
}
|
186
|
-
.transportOptions {
|
187
|
-
display: flex;
|
188
|
-
gap: 10px;
|
189
|
-
margin-top: 10px;
|
190
|
-
}
|
191
|
-
.transportOption {
|
192
|
-
display: flex;
|
193
|
-
align-items: center;
|
194
|
-
padding: 8px 16px;
|
195
|
-
border: 1px solid #ccc;
|
196
|
-
border-radius: 4px;
|
197
|
-
cursor: pointer;
|
198
|
-
}
|
199
|
-
.transportOption.selected {
|
200
|
-
border-color: #007bff;
|
201
|
-
}
|
202
|
-
.transportIcon {
|
203
|
-
margin-right: 8px;
|
204
|
-
}
|
205
|
-
.transportName {
|
206
|
-
font-size: 14px;
|
207
|
-
}
|
File without changes
|