diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index da10ec2..8fe70a6 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -7,7 +7,7 @@ name: Deploy Next.js site to Pages on: # Runs on pushes targeting the default branch push: - branches: ["master"] + branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/README.md b/README.md index 0dc9ea2..4b32b96 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,199 @@ +# MapQaTor Frontend + This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). -## Getting Started +## Project Setup + +Follow the step by step installation procedure to install and run this on your machine. + +## Prerequisites + +Make sure you have node installed in your device. + +**`NodeJs`**: Install Nodejs from [here](https://nodejs.org/en/download/) + +## Installation + + +1. Clone the repo + +```sh +git clone https://github.com/mapqator/mapqator.github.io.git +``` + +2. If you don't have git installed in your device then download zip +3. After installation or download go to the repository and open command line. + +### Configuring + + +2. Install NPM packages -First, run the development server: +```sh +npm install +``` + +3. Ensure backend is configured and running correctly on "http://localhost:5000" (note the port number) + +#### Run the project + +Go to your favourite code editor and run -```bash +```sh npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. +You should find that the project is working! + +## Adding new Map APIs + +Add or edit files in the `src/tools` and `src/mapServices` directories. + + +# Data Collection Tools + + + +## Text Search Object + +| Field Name | Description | +|------------------|--------------------------------------------------| +| `id` | A location identifier (e.g., a Place ID) | +| `displayName` | Display name of the location. | +| `shortFormattedAddress` | Short address of the location. | +| `location` | Latitude and longitude of the location. | +| `mapService` | Map service used for the search (e.g., googleMaps). | + +## Place Details Object + +Attributes of the place details object are unique to the Map Service used. This need to be specified in the adapter. Attributes should be subset of the following: + +`[ "location", + "shortFormattedAddress", + "accessibilityOptions", + "businessStatus", + "googleMapsUri", + "primaryType", + "internationalPhoneNumber", + "nationalPhoneNumber", + "priceLevel", + "rating", + "regularOpeningHours", + "userRatingCount", + "websiteUri", + "allowsDogs", + "curbsidePickup", + "delivery", + "dineIn", + "editorialSummary", + "evChargeOptions", + "fuelOptions", + "goodForChildren", + "goodForGroups", + "goodForWatchingSports", + "liveMusic", + "menuForChildren", + "parkingOptions", + "paymentOptions", + "outdoorSeating", + "reservable", + "restroom", + "servesBeer", + "servesBreakfast", + "servesBrunch", + "servesCocktails", + "servesCoffee", + "servesDessert", + "servesDinner", + "servesLunch", + "servesVegetarianFood", + "servesWine", + "takeout", + "generativeSummary", + "areaSummary" +] +` -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. +## Nearby Search Object -## Learn More +| Field Name | Description | +|------------------|--------------------------------------------------| +| `locationBias` | A location identifier (e.g., a Place ID) specifying the place around which to search | +| `type` | Type of places being searched (e.g., restaurant). | +| `keyword` | A keyword for refining the search (can be empty). | +| `minRating` | Minimum rating filter for the search (e.g., 4). | +| `priceLevels`| List of price levels allowed (e.g., PRICE_LEVEL_MODERATE, PRICE_LEVEL_EXPENSIVE). | +| `rankPreference` | Ranking preference for search results (RELEVANCE, DISTANCE, etc.). | +| `maxResultCount` | Maximum number of results to return. | +| `places` | List of places matching the query criteria. | +| `routingSummaries` | List of navigation details for reaching the places. | -To learn more about Next.js, take a look at the following resources: +## Compute Routes Object -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +| Field Name | Description | +|------------------|--------------------------------------------------| +| `origin` | Origin location identifier. | +| `destination` | Destination location identifier. | +| `intermediates` | List of intermediate locations. | +| `travelMode` | Mode of travel (e.g., DRIVE, WALK). | +| `optimizeWaypointOrder` | Optimize the order of waypoints. | +| `routeModifiers` | Modifiers for the route (e.g., avoidTolls). | +| `routes` | List of routes from origin to destination. | -## Deploy on Vercel +## Search Along Route Object -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +| Field Name | Description | +|------------------|--------------------------------------------------| +| `type` | Type of places being searched (e.g., restaurant). | +| `minRating` | Minimum rating filter for the search (e.g., 4). | +| `priceLevels` | List of price levels allowed (e.g., PRICE_LEVEL_MODERATE, PRICE_LEVEL_EXPENSIVE). | +| `rankPreference` | Ranking preference for search results (RELEVANCE, DISTANCE, etc.). | +| `origin` | Origin location identifier. | +| `destination` | Destination location identifier. | +| `travelMode` | Mode of travel (e.g., DRIVE, WALK). | +| `routeModifiers` | Modifiers for the route (e.g., avoidTolls). | +| `maxResultCount` | Maximum number of results to return. | +| `places` | List of places matching the query criteria. | +| `routes` | List of routes from origin to destination. | diff --git a/package-lock.json b/package-lock.json index 1da9cee..d58e6c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "googlemap", + "name": "MapQaTor", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "googlemap", + "name": "MapQaTor", "version": "0.1.0", "dependencies": { "@emotion/cache": "^11.11.0", @@ -21,6 +21,7 @@ "@mui/x-date-pickers": "^7.7.0", "@react-google-maps/api": "^2.19.3", "@vis.gl/react-google-maps": "^0.9.0", + "apexcharts": "^3.52.0", "axios": "^1.6.8", "date-fns": "^3.6.0", "dayjs": "^1.11.11", @@ -31,7 +32,9 @@ "next": "14.2.2", "pluralize": "^8.0.0", "react": "^18", + "react-apexcharts": "^1.4.1", "react-dom": "^18", + "react-icons": "^5.3.0", "react-toastify": "^10.0.5", "use-places-autocomplete": "^4.0.1" }, @@ -1450,6 +1453,12 @@ "react-dom": ">=16.8.0" } }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -1530,6 +1539,21 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.52.0.tgz", + "integrity": "sha512-7dg0ADKs8AA89iYMZMe2sFDG0XK5PfqllKV9N+i3hKHm3vEtdhwz8AlXGm+/b0nJ6jKiaXsqci5LfVxNhtB+dA==", + "license": "MIT", + "dependencies": { + "@yr/monotone-cubic-spline": "^1.0.3", + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -4824,6 +4848,19 @@ "node": ">=0.10.0" } }, + "node_modules/react-apexcharts": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz", + "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "apexcharts": "^3.41.0", + "react": ">=0.13" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4836,6 +4873,15 @@ "react": "^18.2.0" } }, + "node_modules/react-icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -5487,6 +5533,97 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "license": "MIT", + "dependencies": { + "svg.js": ">=2.3.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==", + "license": "MIT" + }, + "node_modules/svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js/node_modules/svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "license": "MIT", + "dependencies": { + "svg.js": "^2.6.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/tailwindcss": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", diff --git a/package.json b/package.json index ff1cbb3..4e82b7e 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@mui/x-date-pickers": "^7.7.0", "@react-google-maps/api": "^2.19.3", "@vis.gl/react-google-maps": "^0.9.0", + "apexcharts": "^3.52.0", "axios": "^1.6.8", "date-fns": "^3.6.0", "dayjs": "^1.11.11", @@ -33,7 +34,9 @@ "next": "14.2.2", "pluralize": "^8.0.0", "react": "^18", + "react-apexcharts": "^1.4.1", "react-dom": "^18", + "react-icons": "^5.3.0", "react-toastify": "^10.0.5", "use-places-autocomplete": "^4.0.1" }, diff --git a/public/images/azure-maps.png b/public/images/azure-maps.png new file mode 100644 index 0000000..3a963c5 Binary files /dev/null and b/public/images/azure-maps.png differ diff --git a/public/images/google-maps.png b/public/images/google-maps.png new file mode 100644 index 0000000..6c2c77a Binary files /dev/null and b/public/images/google-maps.png differ diff --git a/public/images/graphhopper.png b/public/images/graphhopper.png new file mode 100644 index 0000000..712a368 Binary files /dev/null and b/public/images/graphhopper.png differ diff --git a/public/images/here.png b/public/images/here.png new file mode 100644 index 0000000..3551fef Binary files /dev/null and b/public/images/here.png differ diff --git a/public/images/mapbox-blue.png b/public/images/mapbox-blue.png new file mode 100644 index 0000000..24577ef Binary files /dev/null and b/public/images/mapbox-blue.png differ diff --git a/public/images/mapbox.png b/public/images/mapbox.png new file mode 100644 index 0000000..fa5f194 Binary files /dev/null and b/public/images/mapbox.png differ diff --git a/public/images/openstreetmap.logo.png b/public/images/openstreetmap.logo.png new file mode 100644 index 0000000..ab51808 Binary files /dev/null and b/public/images/openstreetmap.logo.png differ diff --git a/public/images/openstreetmap.logo.svg b/public/images/openstreetmap.logo.svg new file mode 100644 index 0000000..c5e9a6a --- /dev/null +++ b/public/images/openstreetmap.logo.svg @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 010110010011010110010011 + 010110010011010110010011 + + + diff --git a/public/images/tomtom.cover.png b/public/images/tomtom.cover.png new file mode 100644 index 0000000..860e99b Binary files /dev/null and b/public/images/tomtom.cover.png differ diff --git a/public/images/tomtom.jpg b/public/images/tomtom.jpg new file mode 100644 index 0000000..bffdfcf Binary files /dev/null and b/public/images/tomtom.jpg differ diff --git a/public/images/tomtom.png b/public/images/tomtom.png new file mode 100644 index 0000000..54d8b52 Binary files /dev/null and b/public/images/tomtom.png differ diff --git a/src/api/evaluationApi.js b/src/api/evaluationApi.js new file mode 100644 index 0000000..9715f1e --- /dev/null +++ b/src/api/evaluationApi.js @@ -0,0 +1,10 @@ +import Api from "./base"; + +class EvaluationApi extends Api { + insertNewResult = async (list) => { + return await this.post("/evaluation/new", list); + }; +} + +const evaluationApi = new EvaluationApi(); +export default evaluationApi; diff --git a/src/api/geminiApi.js b/src/api/geminiApi.js index 84b5add..acc1e4f 100644 --- a/src/api/geminiApi.js +++ b/src/api/geminiApi.js @@ -1,9 +1,8 @@ import Api from "./base"; class GeminiApi extends Api { - askGeminiLive = async (context, query) => { - console.log(context, query); - return await this.post("/gemini/ask", { context, query }); + askGeminiLive = async (prompt) => { + return await this.post("/gemini/ask", { prompt }); }; } diff --git a/src/api/googleMapsApi.js b/src/api/googleMapsApi.js new file mode 100644 index 0000000..7dec5a4 --- /dev/null +++ b/src/api/googleMapsApi.js @@ -0,0 +1,351 @@ +import MapsApi from "./mapsApi"; + +class GoogleMapsApi extends MapsApi { + textSearch = async (query) => { + const apiCall = { + url: "https://places.googleapis.com/v1/places:searchText", + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "places.id,places.displayName,places.shortFormattedAddress,places.location", + // "X-Goog-Api-Key": ************************, + }, + body: { + textQuery: query, + maxResultCount: 5, + }, + }; + const epochId = Date.now(); // Unique ID for this tool call + const response = await this.post("/map/cached", apiCall); + + if (response.success) { + return { + success: true, + data: { + result: response.data, + apiCallLogs: [ + { + ...apiCall, + uuid: epochId, + result: response.data, + }, + ], + uuid: epochId, + }, + }; + } + return { + success: false, + }; + }; + + placeDetails = async (place_id) => { + const apiCall = { + url: "https://places.googleapis.com/v1/places/" + place_id, + method: "GET", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "id,addressComponents,adrFormatAddress,formattedAddress,location,shortFormattedAddress,types,viewport,accessibilityOptions,businessStatus,displayName,googleMapsUri,primaryType,primaryTypeDisplayName,internationalPhoneNumber,nationalPhoneNumber,priceLevel,rating,regularOpeningHours.weekdayDescriptions,userRatingCount,websiteUri,allowsDogs,curbsidePickup,delivery,dineIn,goodForChildren,goodForGroups,goodForWatchingSports,liveMusic,menuForChildren,outdoorSeating,reservable,restroom,servesBeer,servesBreakfast,servesBrunch,servesCocktails,servesCoffee,servesDessert,servesDinner,servesLunch,servesVegetarianFood,servesWine,takeout", + // "X-Goog-Api-Key": ************************, + }, + }; + const epochId = Date.now(); // Unique ID for this tool call + const response = await this.post("/map/cached", apiCall); + + if (response.success) { + return { + success: true, + data: { + result: response.data, + apiCallLogs: [ + { + ...apiCall, + uuid: epochId, + result: response.data, + }, + ], + uuid: epochId, + }, + }; + } + return { + success: false, + }; + }; + + nearbySearch = async (params) => { + const apiCall = { + url: "https://places.googleapis.com/v1/places:searchText", + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "places.id,places.displayName,places.formattedAddress,places.rating,places.priceLevel,places.shortFormattedAddress,places.userRatingCount,places.location,routingSummaries", + // "X-Goog-Api-Key": ************************, + }, + body: { + textQuery: params.type + " " + params.keyword, + rankPreference: params.rankPreference || "RELEVANCE", // DISTANCE/RELEVANCE/RANK_PREFERENCE_UNSPECIFIED + includedType: params.type, // One type only + minRating: params.minRating, + priceLevels: params.priceLevels, + maxResultCount: params.maxResultCount || 5, + strictTypeFiltering: true, + locationBias: { + circle: { + center: { + latitude: params.lat, + longitude: params.lng, + }, + radius: 0, + }, + }, + languageCode: "en", + routingParameters: { + origin: { + latitude: params.lat, + longitude: params.lng, + }, + travelMode: "WALK", + }, + }, + }; + const epochId = Date.now(); // Unique ID for this tool call + const response = await this.post("/map/cached", apiCall); + + if (response.success) { + return { + success: true, + data: { + result: response.data, + apiCallLogs: [ + { + ...apiCall, + uuid: epochId, + result: response.data, + }, + ], + uuid: epochId, + }, + }; + } + return { + success: false, + }; + }; + + computeRoutes = async (params) => { + const apiCall = { + url: "https://routes.googleapis.com/directions/v2:computeRoutes", + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "routes.distanceMeters,routes.staticDuration,routes.description,routes.localizedValues,routes.optimized_intermediate_waypoint_index,routes.legs.steps.navigationInstruction,routes.legs.steps.transitDetails,routes.legs.localizedValues,routes.legs.steps.travelMode,routes.legs.steps.localizedValues,routes.legs.polyline,routes.polyline", + // "X-Goog-Api-Key": ************************, + }, + body: { + origin: { + placeId: params.origin, + }, + destination: { + placeId: params.destination, + }, + travelMode: params.travelMode, + intermediates: + params.travelMode !== "TRANSIT" + ? params.intermediates?.map((intermediate) => ({ + placeId: intermediate, + })) + : undefined, + routeModifiers: { + avoidTolls: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidTolls + : false, + avoidHighways: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidHighways + : false, + avoidFerries: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidFerries + : false, + avoidIndoor: false, + }, + transitPreferences: + params.travelMode === "TRANSIT" + ? params.transitPreferences + : undefined, + optimizeWaypointOrder: + params.intermediates.length > 0 && + params.travelMode !== "TRANSIT" + ? params.optimizeWaypointOrder + : false, + extraComputations: + params.travelMode === "TRANSIT" + ? [] + : ["HTML_FORMATTED_NAVIGATION_INSTRUCTIONS"], + units: "METRIC", + languageCode: "en", + routingPreference: + params.travelMode === "WALK" || + params.travelMode === "BICYCLE" || + params.travelMode === "TRANSIT" + ? undefined + : "TRAFFIC_UNAWARE", + computeAlternativeRoutes: + params.intermediates.length === 0 + ? params.computeAlternativeRoutes === undefined + ? true + : params.computeAlternativeRoutes + : false, + }, + }; + + const epochId = Date.now(); // Unique ID for this tool call + const response = await this.post("/map/cached", apiCall); + + if (response.success) { + return { + success: true, + data: { + result: response.data, + apiCallLogs: [ + { + ...apiCall, + uuid: epochId, + result: response.data, + }, + ], + uuid: epochId, + }, + }; + } + + return { + success: false, + }; + }; + + searchAlongRoute = async (params) => { + const apiCall1 = { + url: "https://routes.googleapis.com/directions/v2:computeRoutes", + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "routes.distanceMeters,routes.staticDuration,routes.description,routes.localizedValues,routes.optimized_intermediate_waypoint_index,routes.legs.steps.navigationInstruction,routes.legs.steps.transitDetails,routes.legs.localizedValues,routes.legs.steps.travelMode,routes.legs.steps.localizedValues,routes.legs.polyline,routes.polyline", + // "X-Goog-Api-Key": ************************, + }, + body: { + origin: { + placeId: params.origin, + }, + destination: { + placeId: params.destination, + }, + travelMode: params.travelMode, + intermediates: undefined, + routeModifiers: { + avoidTolls: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidTolls + : false, + avoidHighways: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidHighways + : false, + avoidFerries: ["DRIVE", "TWO_WHEELER"].includes( + params.travelMode + ) + ? params.routeModifiers.avoidFerries + : false, + avoidIndoor: false, + }, + transitPreferences: undefined, + optimizeWaypointOrder: false, + extraComputations: + params.travelMode === "TRANSIT" + ? [] + : ["HTML_FORMATTED_NAVIGATION_INSTRUCTIONS"], + units: "METRIC", + languageCode: "en", + routingPreference: + params.travelMode === "WALK" || + params.travelMode === "BICYCLE" || + params.travelMode === "TRANSIT" + ? undefined + : "TRAFFIC_UNAWARE", + computeAlternativeRoutes: false, + }, + }; + + const response1 = await this.post("/map/cached", apiCall1); + + if (!response1.success) return { success: false }; + const apiCall2 = { + url: "https://places.googleapis.com/v1/places:searchText", + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-FieldMask": + "places.id,places.displayName,places.rating,places.priceLevel,places.shortFormattedAddress,places.userRatingCount,places.location", + }, + body: { + textQuery: + params.searchBy === "type" ? params.type : params.keyword, + rankPreference: params.rankPreference || "RELEVANCE", // DISTANCE/RELEVANCE/RANK_PREFERENCE_UNSPECIFIED + includedType: + params.searchBy === "type" ? params.type : undefined, // One type only + minRating: params.minRating, + priceLevels: params.priceLevels, + maxResultCount: params.maxResultCount || 5, + strictTypeFiltering: true, + searchAlongRouteParameters: { + polyline: { + encodedPolyline: + response1.data.routes[0].polyline.encodedPolyline, + }, + }, + languageCode: "en", + }, + }; + + const response2 = await this.post("/map/cached", apiCall2); + + if (!response2.success) return { success: false }; + + const epochId = Date.now(); + + return { + success: true, + data: { + route_response: response1.data, + nearby_response: response2.data, + apiCallLogs: [ + { + ...apiCall1, + uuid: epochId, + result: response1.data, + }, + { + ...apiCall2, + uuid: epochId, + result: response2.data, + }, + ], + uuid: epochId, + }, + }; + }; +} +const mapsApi = new GoogleMapsApi(); +export default mapsApi; diff --git a/src/api/gptApi.js b/src/api/gptApi.js index ea041a4..732062b 100644 --- a/src/api/gptApi.js +++ b/src/api/gptApi.js @@ -9,7 +9,7 @@ class GptApi extends Api { }; askGPTLive = async (context, query) => { console.log(context, query); - return await this.post("/gpt/ask", { context, query }); + return await this.post("/gpt/ask-many", { context, query }); }; generateQuestion = async (context) => { return await this.post("/gpt/generate-question", { context }); diff --git a/src/api/mapApi.js b/src/api/mapApi.js index 0cf847b..f5db3c4 100644 --- a/src/api/mapApi.js +++ b/src/api/mapApi.js @@ -4,23 +4,32 @@ class MapApi extends Api { getDetails = async (place_id) => { return await this.get("/map/details/" + place_id); }; + getDetailsNew = async (place_id) => { + return await this.get("/map/details/new/" + place_id); + }; getNearby = async (params) => { return await this.get( "/map/nearby?lat=" + params.lat + "&lng=" + params.lng + - (params.rankBy !== "distance" + (params.rankPreference !== "distance" ? "&radius=" + params.radius : "") + (params.type !== "" ? "&type=" + params.type : "") + (params.keyword !== "" ? "&keyword=" + params.keyword : "") + "&rankby=" + - params.rankBy + + params.rankPreference + "&location=" + params.location ); }; + searchAlongRoute = async (params) => { + return await this.post("/map/search/along-route", params); + }; + getNearbyNew = async (params) => { + return await this.post("/map/nearby/new", params); + }; getInside = async (params) => { if (params.type === "") return; return await this.get( @@ -34,6 +43,9 @@ class MapApi extends Api { search = async (query) => { return await this.get("/map/search?query=" + query); }; + searchNew = async (query) => { + return await this.post("/map/search/new", { query }); + }; getDistance = async (origin, destination, mode) => { return await this.get( "/map/distance?origin=" + @@ -44,6 +56,10 @@ class MapApi extends Api { mode ); }; + getDistanceNew = async (params) => { + console.log(params); + return await this.post("/map/distance/new", params); + }; getDirections = async (origin, destination, mode) => { return await this.get( "/map/directions?origin=" + @@ -54,6 +70,12 @@ class MapApi extends Api { mode ); }; + getDirectionsNew = async (params) => { + console.log(">", params); + const response = await this.post("/map/directions/new", params); + console.log("<", response); + return response; + }; } const mapApi = new MapApi(); export default mapApi; diff --git a/src/api/mapsApi.js b/src/api/mapsApi.js new file mode 100644 index 0000000..9ec4151 --- /dev/null +++ b/src/api/mapsApi.js @@ -0,0 +1,32 @@ +import Api from "./base"; + +class MapsApi extends Api { + constructor() { + if (new.target === MapsApi) { + throw new TypeError("Cannot construct MapsApi instances directly"); + } + super(); + } + // Abstract methods + textSearch() { + throw new Error("Method 'textSearch()' must be implemented."); + } + + placeDetails() { + throw new Error("Method 'placeDetails()' must be implemented."); + } + + nearbySearch() { + throw new Error("Method 'nearbySearch()' must be implemented."); + } + + computeRoutes() { + throw new Error("Method 'computeRoutes()' must be implemented."); + } + + searchAlongRoute() { + throw new Error("Method 'searchAlongRoute()' must be implemented."); + } +} + +export default MapsApi; diff --git a/src/api/queryApi.js b/src/api/queryApi.js index 18f1af0..95ec1fc 100644 --- a/src/api/queryApi.js +++ b/src/api/queryApi.js @@ -1,15 +1,25 @@ import Api from "./base"; class QueryApi extends Api { - getQueries = async (query) => { - return await this.get("/queries", query); + getQueries = async () => { + return await this.get("/queries"); + }; + getNewQueries = async () => { + console.log("getNewQueries"); + return await this.get("/queries/new"); }; getQuery = async (id) => { return await this.get(`/queries/${id}`); }; + getNewQuery = async (id) => { + return await this.get(`/queries/new/${id}`); + }; createQuery = async (body) => { return await this.post("/queries", body); }; + createNewQuery = async (body) => { + return await this.post("/queries/new", body); + }; createQueryWithEvaluation = async (body) => { return await this.post("/queries/evaluate", body); }; @@ -19,12 +29,18 @@ class QueryApi extends Api { updateQuery = async (id, body) => { return await this.put(`/queries/${id}`, body); }; + updateNewQuery = async (id, body) => { + return await this.put(`/queries/new/${id}`, body); + }; updateQueryWithEvaluation = async (id, body) => { return await this.put(`/queries/${id}/evaluate`, body); }; deleteQuery = async (id) => { return await this.delete(`/queries/${id}`); }; + deleteNewQuery = async (id) => { + return await this.delete(`/queries/new/${id}`); + }; getGPTContext = async (context) => { console.log(context); return await this.post("/queries/gpt/context", { content: context }); @@ -32,6 +48,14 @@ class QueryApi extends Api { annotate = async (query_id, human) => { return await this.post("/queries/annotate/" + query_id, human); }; + submitForEvaluation = async (query_id, context) => { + return await this.post("/queries/" + query_id + "/evaluation", { + context, + }); + }; + getModels = async () => { + return await this.get("/queries/models"); + }; } const queryApi = new QueryApi(); diff --git a/src/app/home/WorkFlow.jsx b/src/app/home/WorkFlow.jsx index 3b42521..08bc134 100644 --- a/src/app/home/WorkFlow.jsx +++ b/src/app/home/WorkFlow.jsx @@ -10,9 +10,12 @@ import QuestionAnswerIcon from "@mui/icons-material/QuestionAnswer"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faRobot } from "@fortawesome/free-solid-svg-icons"; import { + Checklist, Description, KeyboardDoubleArrowDown, KeyboardDoubleArrowRight, + ListAlt, + Save, } from "@mui/icons-material"; export default function WorkFlow() { @@ -22,7 +25,7 @@ export default function WorkFlow() { useEffect(() => { // Show the tooltip after a short delay - const timer = setTimeout(() => setShowTooltip(true), 1000); + const timer = setTimeout(() => setShowTooltip(true), 500); return () => clearTimeout(timer); }, []); @@ -41,9 +44,8 @@ export default function WorkFlow() { }} /> ), - label: "Generate Context", - description: - "Generate rich, place-related contexts using our intuitive interface with Map Services.", + label: "Design Context", + description: "Design place-related contexts using Map Services.", key: "context", to: "/home/context", }, @@ -55,9 +57,9 @@ export default function WorkFlow() { }} /> ), - label: "Create Question", + label: "Create QA Pair", description: - "Easily create relevant questions based on the map contexts you've generated.", + "Create questions and answers based on designed contexts.", key: "question", to: "/home/question", }, @@ -66,29 +68,44 @@ export default function WorkFlow() { // label: "Manage Datasets", // description: "Organize and version your QnA datasets", // }, + // { + // icon: ( + // + // ), + // label: "Evaluate LLMs", + // description: + // "Context + Question pair will be used to evaluate the performance of closed-source LLMs.", + // key: "live_evaluation", + // to: "/home/evaluation", + // }, { + label: "Review and Save", icon: ( - ), - label: "Evaluate LLMs", - description: - "Context + Question pair will be used to evaluate the performance of closed-source LLMs.", + description: "Review and save the created QA pairs for your use.", key: "live_evaluation", - to: "/home/evaluation", + to: "/home/review", }, ]; + console.log("contextStatus", contextStatus, "queryStatus", queryStatus); + return (
{steps.map((step, index) => (
{index < steps.length - 1 && ( <> -
+
diff --git a/src/app/home/answer/page.js b/src/app/home/answer/page.js index e904305..59001cf 100644 --- a/src/app/home/answer/page.js +++ b/src/app/home/answer/page.js @@ -22,6 +22,7 @@ import CorrectAnswerEditor from "@/components/InputFields/CorrectAnswerEditor"; import { useRouter } from "next/navigation"; export default function ProvideAnswerPage() { + return; const { query, context, setAnswerStatus } = useContext(GlobalContext); const [answer, setAnswer] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); @@ -34,7 +35,7 @@ export default function ProvideAnswerPage() { const handleSubmit = async (e) => { e.preventDefault(); setAnswerStatus("saved"); - router.push("/home/summary"); + router.push("/home/review"); }; const handleEditQuestion = () => { diff --git a/src/app/home/context/page.js b/src/app/home/context/page.js index 37a4b03..ce3e2ed 100644 --- a/src/app/home/context/page.js +++ b/src/app/home/context/page.js @@ -3,15 +3,14 @@ import { useContext, useEffect, useState } from "react"; import { Box, Container, Typography } from "@mui/material"; import { GlobalContext } from "@/contexts/GlobalContext"; import ContextGeneratorService from "@/services/contextGeneratorService"; -import ContextStepper from "@/components/Steppers/ContextStepper"; import { AppContext } from "@/contexts/AppContext"; -import example from "@/database/example.json"; +import example from "@/database/newexample.json"; import mapApi from "@/api/mapApi"; import dayjs from "dayjs"; import KeyStoreButton from "@/components/Buttons/KeyStoreButton"; -import { useRouter } from "next/navigation"; +import { useRouter, useSearchParams } from "next/navigation"; +import ContextEditor from "@/components/GoogleMaps/ContextEditor"; export default function ContextGenerator() { - const [activeStep, setActiveStep] = useState(0); const { selectedPlacesMap, setSelectedPlacesMap, @@ -28,14 +27,19 @@ export default function ContextGenerator() { setCurrentInformation, setContextStatus, queryStatus, + activeStep, + setActiveStep, + savedPlacesMap, + setSavedPlacesMap, + setRoutePlacesMap, } = useContext(GlobalContext); - const { savedPlacesMap, setSavedPlacesMap } = useContext(AppContext); - useEffect(() => { const page = window.location.hash.substring(1); setActiveStep(page === "edit" ? 1 : 0); }, []); + + const searchParams = useSearchParams(); // useEffect(() => { // if (queryStatus === "empty") { // router.push("/home"); @@ -44,6 +48,7 @@ export default function ContextGenerator() { const router = useRouter(); const { + initRoutePlacesMap, initSelectedPlacesMap, initNearbyPlacesMap, initPoisMap, @@ -58,6 +63,7 @@ export default function ContextGenerator() { setNearbyPlacesMap(initNearbyPlacesMap); setCurrentInformation(initCurrentInformation); setDirectionInformation(initDirectionInformation); + setRoutePlacesMap(initRoutePlacesMap); setSelectedPlacesMap(initSelectedPlacesMap); setSavedPlacesMap({}); setActiveStep(1); @@ -74,7 +80,14 @@ export default function ContextGenerator() { // }; const onFinish = () => { setContextStatus("saved"); - router.push("/home/question"); + + const params = searchParams.toString(); + + if (params) { + router.push(`/home/question?${params}`); + } else { + router.push("/home/question"); + } }; const handleSave = async (place_id) => { @@ -102,8 +115,8 @@ export default function ContextGenerator() { // for (let place_id in example.places) { // await handleSave(place_id); // } - setSavedPlacesMap(example.saved_places ?? {}); - setSelectedPlacesMap(example.places ?? {}); + setSavedPlacesMap(example.places ?? {}); + setSelectedPlacesMap(example.place_details ?? {}); setDistanceMatrix(example.distance_matrix ?? {}); setDirectionInformation(example.directions ?? {}); setNearbyPlacesMap(example.nearby_places ?? {}); @@ -169,11 +182,11 @@ export default function ContextGenerator() { return ( - -

+ +

Create Geo-Spatial Context Using Map Services

- { // if (queryStatus === "empty") { @@ -78,6 +83,15 @@ export default function LiveEvaluation() { // } // }, [queryStatus]); + const extractJSON = (s) => { + const match = s.match(/{.*?}/); + try { + return JSON.parse(match[1]); + } catch (e) { + return null; + } + }; + const extract = (s) => { for (let char of s) { if (/\d/.test(char)) { @@ -96,18 +110,40 @@ export default function LiveEvaluation() { console.log("Hit Evaluate"); const res = await llmFunction( ContextGeneratorService.convertContextToText(context), - query + { + questions: query.questions, + } ); - if (res.success) { - const option = extract(res.data); - const explanation = extractSubstringInParentheses(res.data); - const verdict = - parseInt(option) - 1 === query.answer.correct - ? "right" - : "wrong"; + if (res.success && res.data.length > 0) { + console.log("LLM response", res.data); + const answers = []; + for (let i = 0; i < res.data.length; i++) { + const option = extract(res.data[i]); + const explanation = extractSubstringInParentheses(res.data[i]); + const verdict = + parseInt(option) - 1 === query.questions[i].answer.correct + ? "right" + : "wrong"; + + console.log("LLM JSON", { + answer: res.data[i], + option, + explanation, + verdict, + }); + answers.push({ + answer: res.data[i], + option, + explanation, + verdict, + }); + } + + console.log("answers", answers); + setLlmResults((prev) => ({ ...prev, - [llm]: { answer: res.data, option, explanation, verdict }, + [llm]: answers, })); } }; @@ -144,7 +180,7 @@ export default function LiveEvaluation() { const handleReset = () => { setQuery((prev) => ({ - ...initQuery, + questions: [initQuery], context: prev.context, context_json: prev.context_json, })); @@ -157,52 +193,42 @@ export default function LiveEvaluation() { ...query, context: ContextGeneratorService.convertContextToText(context), context_json: { - saved_places: savedPlacesMap, - distance_matrix: distanceMatrix, - places: selectedPlacesMap, + places: savedPlacesMap, + // distance_matrix: distanceMatrix, + place_details: selectedPlacesMap, nearby_places: nearbyPlacesMap, - current_information: currentInformation, - pois: poisMap, + // current_information: currentInformation, + // pois: poisMap, directions: directionInformation, }, evaluation: Object.entries(llmResults).map(([llm, result]) => ({ model_id: llmApis[llm].id, + model: llmApis[llm].name, answer: result.answer, verdict: result.verdict, })), }; - if (query.id === undefined) { - const res = await queryApi.createQueryWithEvaluation(newQuery); - if (res.success) { - // update the queries - showSuccess("Query saved successfully"); - const newQueries = [...queries]; - newQueries.unshift(res.data[0]); - setQueries(newQueries); - router.push("/home/my-dataset"); - handleReset(); - } else { - showError("Can't save this query"); - // window.scrollTo(0, 0); - } + const res = await evaluationApi.insertNewResult( + Object.entries(llmResults).map(([llm, result]) => ({ + model_id: llmApis[llm].id, + query_id: query.id, + responses: result, + type: 0, + })) + ); + + if (res.success) { + // setQueries((prev) => + // prev.map((q) => (q.id === query.id ? res.data[0] : q)) + // ); + // update the queries + showSuccess("Query edited successfully"); + router.push("/home/my-dataset"); + handleReset(); } else { - const res = await queryApi.updateQueryWithEvaluation( - query.id, - newQuery - ); - if (res.success) { - setQueries((prev) => - prev.map((q) => (q.id === res.data[0].id ? res.data[0] : q)) - ); - // update the queries - showSuccess("Query edited successfully"); - router.push("/home/my-dataset"); - handleReset(); - } else { - showError("Can't update this query"); - // window.scrollTo(0, 0); - } + showError("Can't update this query"); + // window.scrollTo(0, 0); } }; @@ -227,7 +253,7 @@ export default function LiveEvaluation() { onConfirm={() => { handleDiscard(); }} - text="Your query and evaluation will be lost. Are you sure you want to discard?" + text="Your evaluation will be lost. Are you sure you want to discard?" /> - = 1 ? 0 : 50, - opacity: stage >= 1 ? 1 : 0, - }} - transition={{ duration: 0.5 }} - > - - - - - - - - - Question - - - - - - {query.question} - - - {query.answer.options.map( - (option, index) => ( - - - - - Option {index + 1}:{" "} - {option} - {index === - query.answer - .correct && ( - - )} - - - - - ) - )} - - - - - - - {isProcessing && ( + {query.questions?.map((question, index) => ( + <> = 1 ? 0 : 50, + opacity: stage >= 1 ? 1 : 0, + }} transition={{ duration: 0.5 }} - className="flex justify-center mb-4" > - - - )} - - - {/* {stage >= 3 && ( - - - - - - - - - Ground Truth - - - - Option {query.answer.correct + 1}:{" "} - {query.answer.options[query.answer.correct]} - - - - - - )} */} - - {Object.entries(llmResults).map(([llm, result], index) => ( - - - - - + + + + + + + Question + + + + + - - - - {llmApis[llm].name} Answer + {question.title} - - + {question.answer.options.map( + (option, index) => ( + + + + + Option{" "} + {index + 1}:{" "} + {option} + {index === + question + .answer + .correct && ( + + )} + + + + + ) + )} + + + + + + {isProcessing && ( + - {result.option === "0" - ? "No answer" - : "Option " + - result.option + - ": " + - query.answer.options[ - result.option - 1 - ]} - - + + )} + + {Object.entries(llmResults).map( + ([llm, result], index) => ( + - {result.verdict === "right" ? ( - - ) : ( - - )} - -
- - - + + + + + + + + {llmApis[llm].name}{" "} + Answer + + + + {result[index].option === + "0" + ? "No answer" + : "Option " + + result[index].option + + ": " + + query.questions[index] + .answer.options[ + result[index] + .option - 1 + ]} + + + {result[index].verdict === + "right" ? ( + + ) : ( + + )} + + + + + + ) + )} + ))} {showLoginPrompt && ( @@ -480,10 +505,37 @@ export default function LiveEvaluation() { transition={{ duration: 0.5 }} > {isAuthenticated ? ( - + + + Would you like to save this evaluation? + + + + + + ) : ( )} diff --git a/src/app/home/explore/page.js b/src/app/home/explore/page.js index 08842a5..773ebf3 100644 --- a/src/app/home/explore/page.js +++ b/src/app/home/explore/page.js @@ -1,11 +1,41 @@ "use client"; -import QueryCard from "@/components/Cards/QueryCard"; +import QueryCard from "@/components/Cards/SingleQueryCard"; +import { GlobalContext } from "@/contexts/GlobalContext"; import examples from "@/database/examples.json"; import { Box, Container } from "@mui/material"; import { useRouter } from "next/navigation"; +import { useContext } from "react"; export default function ExplorePage() { const router = useRouter(); + + const { + setSelectedPlacesMap, + setDistanceMatrix, + setNearbyPlacesMap, + setCurrentInformation, + setDirectionInformation, + setContext, + setQuery, + setPoisMap, + setApiCallLogs, + setRoutePlacesMap, + savedPlacesMap, + setSavedPlacesMap, + setMapService, + } = useContext(GlobalContext); + + const handleEdit = async (query) => { + setSavedPlacesMap(query.context_json.places ?? {}); + setSelectedPlacesMap(query.context_json.place_details ?? {}); + setDirectionInformation(query.context_json.directions ?? []); + setNearbyPlacesMap(query.context_json.nearby_places ?? []); + setRoutePlacesMap(query.context_json.route_places ?? []); + setApiCallLogs(query.api_call_logs ?? []); + setQuery(query); + router.push("/home/review"); + }; + return ( @@ -19,8 +49,9 @@ export default function ExplorePage() { router.push("/home/context#edit")} + onEdit={handleEdit} mode="explore" + index={index} /> ))}

diff --git a/src/app/home/my-dataset/page.js b/src/app/home/my-dataset/page.js index 207aeea..41d5c02 100644 --- a/src/app/home/my-dataset/page.js +++ b/src/app/home/my-dataset/page.js @@ -24,8 +24,8 @@ export default function MyQueriesPage() { { - router.push("/home/question"); + onEdit={(query) => { + router.push("/home/review?id=" + query.id); }} /> diff --git a/src/app/home/question/page.js b/src/app/home/question/page.js index deb62e2..a3fd052 100644 --- a/src/app/home/question/page.js +++ b/src/app/home/question/page.js @@ -1,5 +1,5 @@ "use client"; -import React, { useContext, useEffect } from "react"; +import React, { useContext, useEffect, useState } from "react"; import { Box, Typography, @@ -7,6 +7,7 @@ import { Paper, Divider, Container, + IconButton, } from "@mui/material"; import EditIcon from "@mui/icons-material/Edit"; import { GlobalContext } from "@/contexts/GlobalContext"; @@ -19,8 +20,17 @@ import QuestionsContainer from "@/components/Containers/QuestionsContainer"; import ContextGeneratorService from "@/services/contextGeneratorService"; import { useAuth } from "@/contexts/AuthContext"; import { AppContext } from "@/contexts/AppContext"; -import { useRouter } from "next/navigation"; -import QuestionAnswerForm from "@/components/Forms/QuestionAnswerForm"; +import { useRouter, useSearchParams } from "next/navigation"; +import QuestionAnswerForm from "@/components/Forms/SingleQuestionAnswerForm"; +import { + ArrowBack, + ArrowForward, + Assessment, + Clear, + ExpandMore, +} from "@mui/icons-material"; +import ContextPreview from "@/components/GoogleMaps/ContextPreview"; +import StepIndicator from "@/components/StepIndicator"; export default function QuestionCreationPage() { const { @@ -37,11 +47,14 @@ export default function QuestionCreationPage() { contextStatus, queryStatus, setQueryStatus, + routePlacesMap, + savedPlacesMap, } = useContext(GlobalContext); const router = useRouter(); - const { queries, setQueries, savedPlacesMap } = useContext(AppContext); + const { queries, setQueries } = useContext(AppContext); const { isAuthenticated } = useAuth(); + const searchParams = useSearchParams(); // useEffect(() => { // if (contextStatus === "empty") { @@ -49,8 +62,32 @@ export default function QuestionCreationPage() { // } // }, [contextStatus]); + const handleNext = () => { + const params = searchParams.toString(); + setQueryStatus("saved"); + if (params) { + router.push(`/home/review?${params}`); + } else { + router.push("/home/review"); + } + }; + + const handlePrevious = () => { + const params = searchParams.toString(); + if (params) { + router.push(`/home/context?${params}`); + } else { + router.push("/home/context"); + } + }; + const handleContextEdit = () => { - router.push("/home/context"); + const params = searchParams.toString(); + if (params) { + router.push(`/home/context?${params}`); + } else { + router.push("/home/context"); + } }; const onFinish = () => { @@ -59,96 +96,16 @@ export default function QuestionCreationPage() { }; const handleReset = () => { - setQuery((prev) => ({ - ...initQuery, - context: prev.context, - context_json: prev.context_json, - })); + setQuery(initQuery); + setQueryStatus("empty"); + // router.push("/home"); }; + const [contextExpanded, setContextExpanded] = useState(false); const handleSubmit = async (event) => { event.preventDefault(); setQueryStatus("saved"); onFinish(); - return; - - const newQuery = { - ...query, - context: ContextGeneratorService.convertContextToText(context), - context_json: { - saved_places: savedPlacesMap, - distance_matrix: distanceMatrix, - places: selectedPlacesMap, - nearby_places: nearbyPlacesMap, - current_information: currentInformation, - pois: poisMap, - directions: directionInformation, - }, - }; - console.log(newQuery); - if (isAuthenticated) { - if (query.id === undefined) { - const res = await queryApi.createQuery(newQuery); - if (res.success) { - // update the queries - showSuccess("Query saved successfully"); - console.log("Saved query: ", res.data[0]); - const newQueries = [...queries]; - newQueries.unshift(res.data[0]); - setQueries(newQueries); - window.scrollTo(document.getElementById("questions")); - // handleReset(); - onFinish(); - } else { - showError("Can't save this query"); - window.scrollTo(0, 0); - } - } else { - const res = await queryApi.updateQuery(query.id, newQuery); - if (res.success) { - setQueries((prev) => - prev.map((q) => - q.id === res.data[0].id ? res.data[0] : q - ) - ); - // update the queries - showSuccess("Query edited successfully"); - // handleReset(); - onFinish(); - } else { - showError("Can't update this query"); - window.scrollTo(0, 0); - } - } - } else { - if (query.id === undefined) { - const new_id = - "G-" + - queries.filter((item) => item.username === getUserName()) - .length; - const newQueries = [...queries]; - newQueries.unshift({ - ...newQuery, - id: new_id, - username: getUserName(), - human: { - answer: "", - explanation: "", - username: "", - }, - }); - setQueries(newQueries); - window.scrollTo(document.getElementById("questions")); - showSuccess("Query saved successfully"); - } else { - setQueries((prev) => - prev.map((q) => (q.id === query.id ? newQuery : q)) - ); - showSuccess("Query edited successfully"); - } - // handleReset(); - onFinish(); - } }; return ( @@ -157,11 +114,11 @@ export default function QuestionCreationPage() { // sx={{ mt: 4, mb: 4 }} className="min-h-screen" > - -

- Create MCQ Questions based on the Context + +

+ Create QA Pair based on the Context

- + - - {/* -

- - {text === "" && ( -

- No context provided. -

- )} - {text.length > 200 && ( - - )} */} + /> */} + + {Object.keys(savedPlacesMap).length > 0 ? ( + +
+ setContextExpanded((prev) => !prev) + } + > +

+ {contextExpanded + ? "Summarize Context" + : "Visualize Context"} +

+ + + +
+ + {contextExpanded ? ( + <> + + + + ) : ( + <> + + + {ContextGeneratorService.summarizeContext( + savedPlacesMap, + selectedPlacesMap, + nearbyPlacesMap, + directionInformation, + routePlacesMap + ).map((r, index) => ( + + ({index + 1}) {r.label} + + ))} + + + )} +
+ ) : ( +

+ No information added. +

+ )}
- {/* - AI Generated Questions - -
    -
  • Dummy Question 1
  • -
  • Dummy Question 2
  • -
  • Dummy Question 3
  • -
  • Dummy Question 4
  • -
-
*/} + + +
+ +
+ +
+ + + Step 2 of 3 + +
+ +
+ + +
+
{/* {queries.filter((item) => item.username === getUserName()).length > 0 && ( <> @@ -241,6 +284,35 @@ export default function QuestionCreationPage() {

)} */} + {/* {queryStatus === "saved" && ( + + + Would you like to evaluate this query with LLMs? + + + + + + + )} */}
); diff --git a/src/app/home/summary/layout.js b/src/app/home/review/layout.js similarity index 100% rename from src/app/home/summary/layout.js rename to src/app/home/review/layout.js diff --git a/src/app/home/review/page.js b/src/app/home/review/page.js new file mode 100644 index 0000000..020d5c5 --- /dev/null +++ b/src/app/home/review/page.js @@ -0,0 +1,527 @@ +"use client"; +import React, { useContext, useEffect, useState } from "react"; +import { GlobalContext } from "@/contexts/GlobalContext"; +import ContextGeneratorService from "@/services/contextGeneratorService"; +import gptApi from "@/api/gptApi"; +import { motion, AnimatePresence } from "framer-motion"; +import { + Box, + Card, + CardContent, + Typography, + Chip, + CircularProgress, + Grid, + Avatar, + LinearProgress, + Button, + Container, + Paper, + Divider, + IconButton, +} from "@mui/material"; +import ContextPreview from "@/components/GoogleMaps/ContextPreview"; +import CollapsedContext from "@/components/Cards/CollapsedContext"; +import DescriptionIcon from "@mui/icons-material/Description"; +import QuestionMarkIcon from "@mui/icons-material/QuestionMark"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; +import CancelIcon from "@mui/icons-material/Cancel"; +import SmartToyIcon from "@mui/icons-material/SmartToy"; +import { useAuth } from "@/contexts/AuthContext"; +import { useRouter, useSearchParams } from "next/navigation"; +import config from "@/config/config"; +import queryApi from "@/api/queryApi"; +import { AppContext } from "@/contexts/AppContext"; +import { showError, showSuccess } from "@/contexts/ToastProvider"; +import EditIcon from "@mui/icons-material/Edit"; +import Confirmation from "@/components/Dialogs/Confirmation"; +import geminiApi from "@/api/geminiApi"; +import LockIcon from "@mui/icons-material/Lock"; +import SaveIcon from "@mui/icons-material/Save"; +import DeleteIcon from "@mui/icons-material/Delete"; +import { ArrowBack, ArrowForward, ExpandMore } from "@mui/icons-material"; +import OptionsPreview from "@/components/Lists/OptionsPreview"; +import SaveQuery from "@/components/SaveQuery"; +import LoginPrompt from "@/components/LoginPrompts"; +import StepIndicator from "@/components/StepIndicator"; + +// const SaveQuery = ({ onSave, onDiscard }) => { +// const [showSnackbar, setShowSnackbar] = useState(false); + +// const handleSave = () => { +// onSave(); +// setShowSnackbar(true); +// }; + +// return ( +// +// +// Save this query? +// +// +// +// +// +// +// ); +// }; + +// const LoginPrompt = ({ onLogin }) => { +// return ( +// +// +// +// Want to save this query? +// +// +// Log in to save your query for future reference. +// +// +// +// ); +// }; + +export default function Summary() { + const { + query, + initQuery, + setQuery, + context, + selectedPlacesMap, + nearbyPlacesMap, + poisMap, + directionInformation, + distanceMatrix, + currentInformation, + routePlacesMap, + savedPlacesMap, + } = useContext(GlobalContext); + + const { llmResults, setLlmResults, apiCallLogs } = + useContext(GlobalContext); + const { isAuthenticated } = useAuth(); + const { setEvaluationStatus, queryStatus, setQueryStatus } = + useContext(GlobalContext); + const { queries, setQueries } = useContext(AppContext); + const [contextExpanded, setContextExpanded] = useState(false); + + // useEffect(() => { + // if (queryStatus === "empty") { + // router.push("/home"); + // } + // }, [queryStatus]); + + const router = useRouter(); + + const handleLogin = () => { + router.push(config.logoutRedirect); + }; + const searchParams = useSearchParams(); + + const handleContextEdit = () => { + const params = searchParams.toString(); + if (params) { + router.push(`/home/context?${params}`); + } else { + router.push("/home/context"); + } + }; + const handlePrevious = () => { + const params = searchParams.toString(); + if (params) { + router.push(`/home/question?${params}`); + } else { + router.push("/home/question"); + } + }; + + const handleSave = async (queryName) => { + const newQuery = { + ...query, + name: queryName, + context: ContextGeneratorService.convertContextToText( + savedPlacesMap, + selectedPlacesMap, + nearbyPlacesMap, + directionInformation, + routePlacesMap + ), + context_json: { + places: savedPlacesMap, + // distance_matrix: distanceMatrix, + place_details: selectedPlacesMap, + nearby_places: nearbyPlacesMap, + // current_information: currentInformation, + // pois: poisMap, + directions: directionInformation, + route_places: routePlacesMap, + // map_service: mapService, + }, + api_call_logs: apiCallLogs, + }; + + const params = new URLSearchParams(searchParams.toString()); + + if (query.id === undefined) { + const res = await queryApi.createNewQuery(newQuery); + if (res.success) { + // update the queries + showSuccess("Query saved successfully"); + console.log(res.data); + const newQueries = [...queries]; + newQueries.unshift(res.data[0]); + setQueries(newQueries); + setQuery((prev) => ({ + ...prev, + id: res.data[0].id, + })); + handleReset(); + // params.set("id", res.data[0].id); + // router.push(`?${params.toString()}`); + // handleDiscard(); + router.push("/home/my-dataset"); + } else { + showError("Can't save this query"); + // window.scrollTo(0, 0); + } + } else { + const res = await queryApi.updateNewQuery(query.id, newQuery); + if (res.success) { + setQueries((prev) => + prev.map((q) => (q.id === res.data[0].id ? res.data[0] : q)) + ); + handleReset(); + // update the queries + showSuccess("Query edited successfully"); + // handleDiscard(); + router.push("/home/my-dataset"); + } else { + showError("Can't update this query"); + // window.scrollTo(0, 0); + } + } + // handleSubmit(); + // setQueryStatus("saved"); + // window.scrollTo(0, document.body.scrollHeight); + }; + + const handleDiscard = () => { + setQuery({ + questions: [initQuery], + }); + }; + + const [open, setOpen] = useState(false); + const handleEditQuestion = () => { + const params = searchParams.toString(); + if (params) { + router.push(`/home/question?${params}`); + } else { + router.push("/home/question"); + } + }; + + useEffect(() => { + // Update "context" in the query object + const contextText = ContextGeneratorService.convertContextToText( + savedPlacesMap, + selectedPlacesMap, + nearbyPlacesMap, + directionInformation, + routePlacesMap + ); + + setQuery((prev) => ({ + ...prev, + context: contextText, + context_json: { + places: savedPlacesMap, + place_details: selectedPlacesMap, + nearby_places: nearbyPlacesMap, + directions: directionInformation, + route_places: routePlacesMap, + }, + })); + }, [ + savedPlacesMap, + selectedPlacesMap, + nearbyPlacesMap, + directionInformation, + routePlacesMap, + ]); + + const { + initRoutePlacesMap, + initSelectedPlacesMap, + initNearbyPlacesMap, + initPoisMap, + initDistanceMatrix, + initDirectionInformation, + initCurrentInformation, + + setRoutePlacesMap, + setSelectedPlacesMap, + setNearbyPlacesMap, + setDirectionInformation, + setSavedPlacesMap, + setActiveStep, + setContext, + } = useContext(GlobalContext); + + const handleReset = () => { + setNearbyPlacesMap(initNearbyPlacesMap); + setDirectionInformation(initDirectionInformation); + setRoutePlacesMap(initRoutePlacesMap); + setSelectedPlacesMap(initSelectedPlacesMap); + setSavedPlacesMap({}); + setQuery(initQuery); + setActiveStep(1); + setContext([]); + }; + + const handleNext = () => { + handleReset(); + router.push("/home/context"); + }; + + return ( + + +

+ Review and Save to Dataset +

+ { + handleDiscard(); + }} + text="Your query and evaluation will be lost. Are you sure you want to discard?" + /> + + + + + + + + Context + + + + + + {Object.keys(savedPlacesMap).length > 0 ? ( + +
+ setContextExpanded((prev) => !prev) + } + > +

+ {contextExpanded + ? "Summarize Context" + : "Visualize Context"} +

+ + + +
+ + {contextExpanded ? ( + <> + + + + ) : ( + <> + + + {ContextGeneratorService.summarizeContext( + savedPlacesMap, + selectedPlacesMap, + nearbyPlacesMap, + directionInformation, + routePlacesMap + ).map((r, index) => ( + + ({index + 1}) {r.label} + + ))} + + + )} +
+ ) : ( +

+ No information added. +

+ )} +
+
+ + + + + + + + + Questions + + + + +
+
+ + Question: + + + +
+ {query.question} +
+
+ {query.answer && ( + + )} + + {/* */} +
+
+
+
+
+ + {isAuthenticated ? ( + + ) : ( + + )} + + + +
+ +
+ +
+ + + Step 3 of 3 + +
+
+ +
+
+
+
+ ); +} diff --git a/src/app/home/summary/page.js b/src/app/home/summary/page.js deleted file mode 100644 index 5f44382..0000000 --- a/src/app/home/summary/page.js +++ /dev/null @@ -1,308 +0,0 @@ -"use client"; -import React, { useContext, useEffect, useState } from "react"; -import { GlobalContext } from "@/contexts/GlobalContext"; -import ContextGeneratorService from "@/services/contextGeneratorService"; -import gptApi from "@/api/gptApi"; -import { motion, AnimatePresence } from "framer-motion"; -import { - Box, - Card, - CardContent, - Typography, - Chip, - CircularProgress, - Grid, - Avatar, - LinearProgress, - Button, - Container, -} from "@mui/material"; -import ContextPreview from "@/components/Cards/ContextPreview"; -import CollapsedContext from "@/components/Cards/CollapsedContext"; -import DescriptionIcon from "@mui/icons-material/Description"; -import QuestionMarkIcon from "@mui/icons-material/QuestionMark"; -import CheckCircleIcon from "@mui/icons-material/CheckCircle"; -import CancelIcon from "@mui/icons-material/Cancel"; -import SmartToyIcon from "@mui/icons-material/SmartToy"; -import { useAuth } from "@/contexts/AuthContext"; -import { useRouter } from "next/navigation"; -import config from "@/config/config"; -import queryApi from "@/api/queryApi"; -import { AppContext } from "@/contexts/AppContext"; -import { showError, showSuccess } from "@/contexts/ToastProvider"; -import EditIcon from "@mui/icons-material/Edit"; -import Confirmation from "@/components/Dialogs/Confirmation"; -import geminiApi from "@/api/geminiApi"; -import LockIcon from "@mui/icons-material/Lock"; -import SaveIcon from "@mui/icons-material/Save"; -import DeleteIcon from "@mui/icons-material/Delete"; - -const SaveQuery = ({ onSave, onDiscard }) => { - const [showSnackbar, setShowSnackbar] = useState(false); - - const handleSave = () => { - onSave(); - setShowSnackbar(true); - }; - - return ( - - - Save this query? - - - - - - - ); -}; - -const LoginPrompt = ({ onLogin }) => { - return ( - - - - Want to save this query? - - - Log in to save your query for future reference. - - - - ); -}; -export default function LiveEvaluation() { - const { - query, - initQuery, - setQuery, - context, - selectedPlacesMap, - nearbyPlacesMap, - poisMap, - directionInformation, - distanceMatrix, - currentInformation, - } = useContext(GlobalContext); - - const { llmResults, setLlmResults } = useContext(GlobalContext); - const { isAuthenticated } = useAuth(); - const { setEvaluationStatus, queryStatus } = useContext(GlobalContext); - const { queries, setQueries, savedPlacesMap } = useContext(AppContext); - - useEffect(() => { - if (queryStatus === "empty") { - router.push("/home"); - } - }, [queryStatus]); - - const router = useRouter(); - - const handleLogin = () => { - router.push(config.logoutRedirect); - }; - - const handleReset = () => { - setQuery((prev) => ({ - ...initQuery, - context: prev.context, - context_json: prev.context_json, - })); - setLlmResults({}); - }; - - const handleSave = async () => { - const newQuery = { - ...query, - context: ContextGeneratorService.convertContextToText(context), - context_json: { - saved_places: savedPlacesMap, - distance_matrix: distanceMatrix, - places: selectedPlacesMap, - nearby_places: nearbyPlacesMap, - current_information: currentInformation, - pois: poisMap, - directions: directionInformation, - }, - }; - - if (query.id === undefined) { - const res = await queryApi.createQuery(newQuery); - if (res.success) { - // update the queries - showSuccess("Query saved successfully"); - const newQueries = [...queries]; - newQueries.unshift(res.data[0]); - setQueries(newQueries); - handleReset(); - router.push("/home/my-dataset"); - } else { - showError("Can't save this query"); - // window.scrollTo(0, 0); - } - } else { - const res = await queryApi.updateQuery(query.id, newQuery); - if (res.success) { - setQueries((prev) => - prev.map((q) => (q.id === res.data[0].id ? res.data[0] : q)) - ); - // update the queries - showSuccess("Query edited successfully"); - handleReset(); - router.push("/home/my-dataset"); - } else { - showError("Can't update this query"); - // window.scrollTo(0, 0); - } - } - }; - - const handleDiscard = () => { - console.log("Discarding query"); - // setShowSavePrompt(false); - handleReset(); - router.push("/home"); - }; - - const [open, setOpen] = useState(false); - const handleEditQuestion = () => { - router.push("/home/question"); - }; - - return ( - - - { - handleDiscard(); - }} - text="Your query and evaluation will be lost. Are you sure you want to discard?" - /> - - - - - - - - - Question - - - - - {query.question} - - - {query.answer.options.map((option, index) => ( - - - - - Option {index + 1}: {option} - {index === - query.answer.correct && ( - - )} - - - - - ))} - - - - - - - - - - - - - Reference Information - - - - - - - - {isAuthenticated ? ( - - ) : ( - - )} - - - ); -} diff --git a/src/app/landing/page.js b/src/app/landing/page.js index 073e85a..f3edf85 100644 --- a/src/app/landing/page.js +++ b/src/app/landing/page.js @@ -19,7 +19,7 @@ export default function PageComponent() { ? process.env.REACT_APP_BASE_URL : process.env.NODE_ENV === "development" ? "" - : "https://mahirlabibdihan.github.io/mapquest" + : "https://mapqator.github.io" ); const [showContent, setShowContent] = useState(false); const router = useRouter(); @@ -84,7 +84,6 @@ export default function PageComponent() { variant="h3" component="div" sx={{ - // ml: 2, color: "#333", fontWeight: "bold", fontSize: "5rem", @@ -105,28 +104,12 @@ export default function PageComponent() { transform: "translateY(-10px)", }} className="h-3 font-mono" - // style={{}} > A Tool for NLP and Geo-Spatial Researchers
- - {/* - MapQuest - */} - Create, Manage, and Evaluate Geo-Spatial QnA from Map Services + + Read our{" "} + + research paper + {" "} + to learn more about the methodology and findings + - router.push( - // isAuthenticated - // ? - config.loginRedirect + "#onboard" - // : config.logoutRedirect - ) + router.push(config.loginRedirect + "#onboard") } > Start Your Adventure @@ -196,23 +199,6 @@ export default function PageComponent() { - {/*
- - - Developed by Mahir Labib Dihan - - -
*/} ); } diff --git a/src/app/layout.js b/src/app/layout.js index a44eece..5d12615 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -11,18 +11,28 @@ import { GitHub, LinkedIn, Mail } from "@mui/icons-material"; import Footer from "./footer"; import GlobalContextProvider from "@/contexts/GlobalContext"; export const metadata = { - metadataBase: new URL("https://mahirlabibdihan.github.io/mapquest"), + metadataBase: new URL("https://mapqator.github.io/"), title: { template: "%s | MapQaTor", default: "MapQaTor", }, - - description: "Map dataset creator", + verification: { + google: "9pM5JfTm1_c-Tmup10c-YeYhrLtBVv_tnZJ_mbvxGWQ", + }, + description: "A System for Efficient Annotation of Map Query Datasets", // openGraph: { // title: "Title webtsite", // description: "this is the desciption", // image: "url/image.png", // }, + keywords: [ + "mapqator", + "mapeval", + "mahir labib dihan", + "mapqa", + "mapqa dataset", + "google maps dataset", + ], }; export default function RootLayout({ children }) { diff --git a/src/app/login/page.js b/src/app/login/page.js index 17f65de..1dc0c5b 100644 --- a/src/app/login/page.js +++ b/src/app/login/page.js @@ -79,7 +79,7 @@ const Login = () => { style={{ transform: "translateY(-120%)" }} // Move up by 20px > router.push("landing")} + onClick={() => router.push("/")} className="cursor-pointer flex-row items-end flex w-full gap-2" >
@@ -142,6 +142,16 @@ const Login = () => { +
{ + // // setLoading(true); + // navigate("/"); + // }} + className="cursor-pointer text-gray-400" + style={{ transform: "translateY(20%)" }} // Move up by 20px + > + Note: Registration is not available for now. +
diff --git a/src/app/opengraph-image.jpeg b/src/app/mapqator.jpeg similarity index 100% rename from src/app/opengraph-image.jpeg rename to src/app/mapqator.jpeg diff --git a/src/app/old-home/ContextGenerator.jsx b/src/app/old-home/ContextGenerator.jsx deleted file mode 100644 index fd3e7d5..0000000 --- a/src/app/old-home/ContextGenerator.jsx +++ /dev/null @@ -1,541 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import { Select, MenuItem, Button, TextField, IconButton } from "@mui/material"; -import PlaceInformation from "./PlaceInformation"; -import DistanceInformation from "./DistanceInformation"; -import NearbyInformation from "./NearbyInformation"; -import ContextPreview from "./ContextPreview"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faRefresh } from "@fortawesome/free-solid-svg-icons"; -import CurrentInformation from "./CurrentInformation"; -import { format } from "date-fns"; -import POI from "./POI"; -import DirectionInformation from "./DirectionInformation"; -import HybridSearch from "./HybridSearch"; -import { LoadingButton } from "@mui/lab"; -import { Start } from "@mui/icons-material"; - -export default function ContextGenerator({ - setContextJSON, - context, - setContext, - distanceMatrix, - setDistanceMatrix, - selectedPlacesMap, - setSelectedPlacesMap, - nearbyPlacesMap, - setNearbyPlacesMap, - currentInformation, - setCurrentInformation, - directionInformation, - setDirectionInformation, - poisMap, - setPoisMap, - savedPlacesMap, - setSavedPlacesMap, -}) { - useEffect(() => { - generateContext(); - }, [ - distanceMatrix, - selectedPlacesMap, - nearbyPlacesMap, - savedPlacesMap, - currentInformation, - directionInformation, - poisMap, - ]); - - const generateContext = async () => { - let newContext = []; - - for (const place_id of Object.keys(selectedPlacesMap)) { - // if (!savedPlacesMap[place_id]) { - // await handleSave(place_id); - // } - const text = placeToContext(place_id); - if (text !== "") { - newContext.push( - `Information of ${ - // selectedPlacesMap[place_id].alias || - savedPlacesMap[place_id].name - }:` - ); - // Split the text into lines and add to context - text.split("\n").forEach((line) => { - newContext.push(line); - }); - } - } - - Object.keys(distanceMatrix).forEach((from_id) => { - Object.keys(distanceMatrix[from_id]).forEach((to_id) => { - Object.keys(distanceMatrix[from_id][to_id]).forEach((mode) => { - if (mode === "transit") { - newContext.push( - `Distance from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by public transport is ${ - distanceMatrix[from_id][to_id][mode].distance - } (${ - distanceMatrix[from_id][to_id][mode].duration - }).` - ); - } else if (mode === "driving") { - newContext.push( - `Distance from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by car is ${ - distanceMatrix[from_id][to_id][mode].distance - } (${ - distanceMatrix[from_id][to_id][mode].duration - }).` - ); - } else if (mode === "bicycling") { - newContext.push( - `Distance from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by cycle is ${ - distanceMatrix[from_id][to_id][mode].distance - } (${ - distanceMatrix[from_id][to_id][mode].duration - }).` - ); - } else if (mode === "walking") { - newContext.push( - `Distance from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } on foot is ${ - distanceMatrix[from_id][to_id][mode].distance - } (${ - distanceMatrix[from_id][to_id][mode].duration - }).` - ); - } - }); - }); - }); - - Object.keys(directionInformation).forEach((from_id) => { - Object.keys(directionInformation[from_id]).forEach((to_id) => { - Object.keys(directionInformation[from_id][to_id]).forEach( - (mode) => { - if (mode === "transit") { - newContext.push( - `There are ${ - directionInformation[from_id][to_id][mode] - .routes.length - } routes from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by public transport. They are:` - ); - } else if (mode === "driving") { - newContext.push( - `There are ${ - directionInformation[from_id][to_id][mode] - .routes.length - } routes from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by car. They are:` - ); - } else if (mode === "bicycling") { - newContext.push( - `There are ${ - directionInformation[from_id][to_id][mode] - .routes.length - } routes from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } by cycle. They are:` - ); - } else if (mode === "walking") { - newContext.push( - `There are ${ - directionInformation[from_id][to_id][mode] - .routes.length - } routes from ${ - // selectedPlacesMap[from_id].alias || - savedPlacesMap[from_id].name - } to ${ - // selectedPlacesMap[to_id].alias || - savedPlacesMap[to_id].name - } on foot. They are:` - ); - } - - directionInformation[from_id][to_id][ - mode - ].routes.forEach((route, index) => { - newContext.push( - `${index + 1}. Via ${route.label} | ${ - route.duration - } | ${route.distance}` - ); - - if ( - directionInformation[from_id][to_id][mode] - .showSteps - ) { - route.steps.forEach((step, index) => { - newContext.push(` - ${step}`); - }); - } - }); - } - ); - }); - }); - - Object.keys(nearbyPlacesMap).forEach((place_id, index) => { - nearbyPlacesMap[place_id].forEach((e) => { - newContext.push( - `Nearby places of ${ - // selectedPlacesMap[place_id].alias || - savedPlacesMap[place_id].name - } ${e.type === "any" ? "" : 'of type "' + e.type + '"'} ${ - e.keyword !== "" - ? 'with keyword "' + e.keyword + '"' - : "" - } are (${ - e.hasRadius - ? "in " + e.radius + " m radius" - : "sorted by distance in ascending order" - }):` - ); - let counter = 1; - e.places.forEach((near_place) => { - if (near_place.selected) { - newContext.push( - `${counter}. ${ - // selectedPlacesMap[near_place.place_id]?.alias || - savedPlacesMap[near_place.place_id]?.name || - near_place.name - } (${ - near_place.formatted_address || - savedPlacesMap[near_place.place_id]?.vicinity - })` - ); - counter++; - } - }); - - newContext.push("\n"); - }); - }); - - Object.keys(poisMap).forEach((place_id, index) => { - poisMap[place_id].forEach((poi) => { - newContext.push( - `Places in ${ - // selectedPlacesMap[place_id].alias || - savedPlacesMap[place_id].name - } of type \"${poi.type}\" are:` - ); - let counter = 1; - poi.places.forEach((place) => { - if (place.selected) { - newContext.push( - `${counter}. ${ - // selectedPlacesMap[place.place_id]?.alias || - savedPlacesMap[place.place_id]?.name || - place.name - } (${ - place.formatted_address || - savedPlacesMap[place.place_id]?.vicinity - })` - ); - counter++; - } - }); - - newContext.push(""); - }); - }); - - // if (currentInformation.time && currentInformation.day !== "") { - // newContext.push( - // `Current time is ${currentInformation.time.format( - // "h:mm a" - // )} on ${currentInformation.day}.` - // ); - // } else if (currentInformation.time) { - // newContext.push( - // `Current time is ${currentInformation.time.format("h:mm a")}.` - // ); - // } else if (currentInformation.day !== "") { - // newContext.push(`Today is ${currentInformation.day}.`); - // } - - // if (currentInformation.location !== "") { - // newContext.push( - // `Current location of user is ${ - // // selectedPlacesMap[currentInformation.location]?.alias || - // savedPlacesMap[currentInformation.location]?.name - // }.` - // ); - // } - - setContext(newContext); - - console.log({ - distance_matrix: distanceMatrix, - places: selectedPlacesMap, - nearby_places: nearbyPlacesMap, - current_information: currentInformation, - pois: poisMap, - directions: directionInformation, - }); - - setContextJSON({ - distance_matrix: distanceMatrix, - places: selectedPlacesMap, - nearby_places: nearbyPlacesMap, - current_information: currentInformation, - pois: poisMap, - directions: directionInformation, - }); - }; - - const placeToContext = (place_id) => { - let place = savedPlacesMap[place_id]; - if (!place) return ""; - - let attributes = selectedPlacesMap[place_id].selectedAttributes; - let text = ""; - - if ( - attributes.includes("formatted_address") || - (attributes.includes("geometry") && place.geometry.location) - ) { - const lat = - typeof place.geometry.location.lat === "function" - ? place.geometry.location.lat() - : place.geometry.location.lat; - const lng = - typeof place.geometry.location.lng === "function" - ? place.geometry.location.lng() - : place.geometry.location.lng; - text += `- Location: ${ - attributes.includes("formatted_address") - ? place.formatted_address - : "" - }${ - attributes.includes("geometry") - ? "(" + lat + ", " + lng + ")" - : "" - }.\n`; - } - if (attributes.includes("opening_hours")) { - text += `- Open: ${place.opening_hours.weekday_text.join(", ")}.\n`; - } - if (attributes.includes("rating")) { - text += `- Rating: ${place.rating}. (${place.user_ratings_total} ratings).\n`; - } - - if (attributes.includes("reviews")) { - text += `- Reviews: \n${place.reviews - .map((review, index) => { - console.log(review.text); - return ` ${index + 1}. ${review.author_name} (Rating: ${ - review.rating - }): ${review.text}\n`; - }) - .join("")} `; // Use .join('') to concatenate without commas - } - console.log(text); - if (attributes.includes("price_level")) { - // - 0 Free - // - 1 Inexpensive - // - 2 Moderate - // - 3 Expensive - // - 4 Very Expensive - // Convert price level from number to string - - let priceLevel = ""; - const priceMap = [ - "Free", - "Inexpensive", - "Moderate", - "Expensive", - "Very Expensive", - ]; - - text += `- Price Level: ${priceMap[place.price_level]}.\n`; - } - - if (attributes.includes("delivery")) { - text += place.delivery - ? "- Delivery Available.\n" - : "- Delivery Not Available.\n"; - } - - if (attributes.includes("dine_in")) { - text += place.dine_in - ? "- Dine In Available.\n" - : "- Dine In Not Available.\n"; - } - - if (attributes.includes("takeaway")) { - text += place.takeaway - ? "- Takeaway Available.\n" - : "- Takeaway Not Available.\n"; - } - - if (attributes.includes("reservable")) { - text += place.reservable - ? "- Reservable.\n" - : "- Not Reservable.\n"; - } - - if (attributes.includes("wheelchair_accessible_entrance")) { - text += place.wheelchair_accessible_entrance - ? "- Wheelchair Accessible Entrance.\n" - : "- Not Wheelchair Accessible Entrance.\n"; - } - - return text; - }; - - return ( -
-
- { - setPoisMap({}); - setDistanceMatrix({}); - setNearbyPlacesMap({}); - setContext([]); - setContextJSON({}); - setCurrentInformation({ - time: null, - day: "", - location: "", - }); - setDirectionInformation({}); - setSelectedPlacesMap({}); - }} - > - - -
-
-

Context Generator

-

Generate context for a given question

-

-
- - - - - - - - - - - - {/* */} - - {/* */} -
- ); -} diff --git a/src/app/old-home/ContextPreview.jsx b/src/app/old-home/ContextPreview.jsx deleted file mode 100644 index 38c3d36..0000000 --- a/src/app/old-home/ContextPreview.jsx +++ /dev/null @@ -1,45 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { Select, MenuItem, Button, TextField } from "@mui/material"; - -export function ContextViewer({ context }) { - return ( -
- {context.length > 0 ? ( - context.map((text, index) => ( -

- )) - ) : ( -

- No context generated. Add information first. -

- )} -
- ); -} -export default function ContextPreview({ context }) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
-
-

- Generated Context -

-

- Context generated by our system -

-
- -
- ); -} diff --git a/src/app/old-home/CurrentInformation.jsx b/src/app/old-home/CurrentInformation.jsx deleted file mode 100644 index 11a6ea1..0000000 --- a/src/app/old-home/CurrentInformation.jsx +++ /dev/null @@ -1,205 +0,0 @@ -"use client"; -import { - FormLabel, - RadioGroup, - FormControlLabel, - Radio, - IconButton, - Button, - TextField, - Select, - MenuItem, -} from "@mui/material"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { DemoContainer } from "@mui/x-date-pickers/internals/demo"; -import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; -import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; -import { TimePicker } from "@mui/x-date-pickers/TimePicker"; -import { MobileTimePicker } from "@mui/x-date-pickers/MobileTimePicker"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; - -export function Parameters({ - selectedPlacesMap, - currentInformation, - setCurrentInformation, - savedPlacesMap, -}) { - return ( -
-
-
- - - - setCurrentInformation((prev) => ({ - ...prev, - time: newValue, - })) - } - slotProps={{ - textField: { - fullWidth: true, - size: "small", - }, - }} - /> - - -
- - { - setCurrentInformation((prev) => ({ - ...prev, - time: null, - })); - }} - sx={{ height: "2rem", width: "2rem" }} - > - - -
- -
- - - Current Day - - - - { - setCurrentInformation((prev) => ({ - ...prev, - day: "", - })); - }} - sx={{ height: "2rem", width: "2rem" }} - > - - -
- -
- - - Current location - - - - { - setCurrentInformation((prev) => ({ - ...prev, - location: "", - })); - }} - sx={{ height: "2rem", width: "2rem" }} - > - - -
-
- ); -} -export default function CurrentInformation({ - selectedPlacesMap, - currentInformation, - setCurrentInformation, - savedPlacesMap, -}) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
-
-

- Current Information -

-

- Some information about current situation -

-
- -
- ); -} diff --git a/src/app/old-home/DatasetCreator.jsx b/src/app/old-home/DatasetCreator.jsx deleted file mode 100644 index 2b90025..0000000 --- a/src/app/old-home/DatasetCreator.jsx +++ /dev/null @@ -1,231 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import queryApi from "@/api/queryApi"; -import FormControl from "@mui/material/FormControl"; -import { - FormLabel, - RadioGroup, - FormControlLabel, - Radio, - IconButton, - Button, - TextField, - Pagination, - Select, - OutlinedInput, - MenuItem, - InputLabel, -} from "@mui/material"; -import QueryCard from "./QueryCard"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faRefresh, faTrash } from "@fortawesome/free-solid-svg-icons"; -import QueryForm from "./QueryForm"; -import Evaluation from "./Evaluation"; -import DatasetInformation from "./DatasetInformation"; -import { showSuccess, showToast } from "./home"; -import { LoadingButton } from "@mui/lab"; -import { Refresh } from "@mui/icons-material"; -import categories from "./categories.json"; -const itemsPerPage = 5; - -export default function DatasetCreator({ - contextJSON, - setContextJSON, - context, - setContext, - setSavedPlacesMap, - setSelectedPlacesMap, - setDistanceMatrix, - setNearbyPlacesMap, - setDirectionInformation, - setCurrentInformation, - setPoisMap, -}) { - const [queries, setQueries] = useState([]); - const [filteredQueries, setFilteredQueries] = useState([]); - const [loading, setLoading] = useState(false); - const [category, setCategory] = useState(""); - const [fetched, setFetched] = useState(false); - const fetchQueries = async () => { - setLoading(true); - try { - const res = await queryApi.getQueries(); - if (res.success) { - console.log("Data: ", res.data); - setQueries(res.data); - setFetched(true); - setLoading(false); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - - const [data, setData] = useState([]); - const [page, setPage] = useState(1); - - const [pageCount, setPageCount] = useState(0); - - useEffect(() => { - if (process.env.NODE_ENV === "production") { - fetchQueries(); - } - }, []); - - useEffect(() => { - const start = (page - 1) * itemsPerPage; - const end = start + itemsPerPage; - const newQueries = queries.filter( - (query) => - category === "" || query.classification.includes(category) - ); - setFilteredQueries(newQueries); - setPageCount(Math.ceil(newQueries.length / itemsPerPage)); - setData(newQueries.slice(start, end)); - }, [page, queries, category]); - - const handlePagination = (event, value) => { - setPage(value); - }; - - const handleSave = async (query) => { - const res = await queryApi.createQuery(query); - if (res.success) { - // update the queries - const newQueries = [...queries]; - // push front - newQueries.unshift(res.data[0]); - setQueries(newQueries); - showSuccess("Query saved successfully", res); - } else { - showToast("Can't save this query", "error"); - } - }; - - const handleEdit = async (query, index) => { - // console.log("Editing query: ", query, queries[index]); - // return; - const res = await queryApi.updateQuery( - filteredQueries[index].id, - query - ); - if (res.success) { - // update the queries - console.log("New Query: ", res.data[0]); - setQueries((prevQueries) => - prevQueries.map((query, i) => - query.id === res.data[0].id ? res.data[0] : query - ) - ); - showSuccess("Query edited successfully", res); - } - }; - const handleDelete = async (index) => { - try { - const res = await queryApi.deleteQuery(queries[index].id); - if (res.success) { - console.log("Data: ", res.data); - // update the queries - const newQueries = [...queries]; - newQueries.splice(index, 1); - setQueries(newQueries); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - return ( -
-
-

Map Dataset Creator

-

- Write question and answers with appropriate contexts -

-

-
- - {/*

*/} - {/*

Previous Queries

*/} - {fetched ? ( - <> - - -
-
- -
- - {/* - Category - */} - - - {data.map((query, index) => ( - - ))} -
- - ) : ( -
- } - loadingPosition="end" - > - Load Dataset - -
- )} -
- ); -} diff --git a/src/app/old-home/DatasetInformation.jsx b/src/app/old-home/DatasetInformation.jsx deleted file mode 100644 index c5175f8..0000000 --- a/src/app/old-home/DatasetInformation.jsx +++ /dev/null @@ -1,75 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; - -export default function DatasetInformation({ queries }) { - const [state, setState] = useState(null); - useEffect(() => { - const tmp = {}; - let valid_questions = 0; - let total_questions = 0; - let questions_with_context = 0; - let questions_with_answer = 0; - - queries.forEach((query) => { - total_questions++; - if (query.context !== "") { - questions_with_context++; - } - if (query.answer.correct !== -1) { - questions_with_answer++; - } - if (query.context !== "" && query.answer.correct !== -1) { - const invalid = query.evaluation?.find( - (e) => - e.model !== "mistralai/Mixtral-8x7B-Instruct-v0.1" && - e.verdict === "invalid" - ); - if (!invalid) valid_questions++; - } - }); - tmp["total_questions"] = total_questions; - tmp["questions_with_context"] = questions_with_context; - tmp["questions_with_answer"] = questions_with_answer; - tmp["valid_questions"] = valid_questions; - setState(tmp); - }, [queries]); - return ( -
-
-

Dataset Information

-
-
-
-

- Total Questions -

-

No Context

-

- No Ground Truth -

-

- Valid Questions -

-
-
-
-

- {state?.total_questions} -

-

- {(state?.total_questions ?? 0) - - (state?.questions_with_context ?? 0)} -

-

- {(state?.total_questions ?? 0) - - (state?.questions_with_answer ?? 0)} -

-

- {state?.valid_questions} -

-
-
-
- ); -} diff --git a/src/app/old-home/DirectionInformation.jsx b/src/app/old-home/DirectionInformation.jsx deleted file mode 100644 index 1d1d002..0000000 --- a/src/app/old-home/DirectionInformation.jsx +++ /dev/null @@ -1,460 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import mapApi from "@/api/mapApi"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { Select, MenuItem, Button, TextField, IconButton } from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faChevronDown, - faChevronUp, - faTrashCan, -} from "@fortawesome/free-solid-svg-icons"; -import { Add, CheckBox, Radio } from "@mui/icons-material"; -import { LoadingButton } from "@mui/lab"; -function DirectionCard({ - selectedPlacesMap, - savedPlacesMap, - directionInformation, - setDirectionInformation, - mode, - index2, - from_id, - to_id, -}) { - const [expanded, setExpanded] = useState(false); - return ( -
-
-

- {savedPlacesMap[to_id].name || - selectedPlacesMap[to_id].alias} -

-

{mode}

-

- {directionInformation[from_id][to_id][mode].routes.length} -

-
- { - const newDirectionMatrix = { - ...directionInformation, - }; - newDirectionMatrix[from_id][to_id][mode].showSteps = - !newDirectionMatrix[from_id][to_id][mode] - .showSteps; - setDirectionInformation(newDirectionMatrix); - }} - className="cursor-pointer h-5 w-5" - /> -
-
- { - const newDirectionMatrix = { - ...directionInformation, - }; - delete newDirectionMatrix[from_id][to_id][mode]; - if ( - Object.keys(newDirectionMatrix[from_id][to_id]) - .length === 0 - ) - delete newDirectionMatrix[from_id][to_id]; - if ( - Object.keys(newDirectionMatrix[from_id]) - .length === 0 - ) - delete newDirectionMatrix[from_id]; - setDirectionInformation(newDirectionMatrix); - }} - > -
- -
-
-
- -
- setExpanded((prev) => !prev)} - > -
- -
-
-
-
- {expanded && ( -
- {directionInformation[from_id][to_id][mode].routes.map( - (route, index) => ( -
-
-

- Via {route.label} -

-

- {route.duration} -

-

- {route.distance} -

-
- {directionInformation[from_id][to_id][mode] - .showSteps && ( -
- {route.steps.map((step, index1) => ( -

- ))} -

- )} -
- ) - )} -
- )} -
- ); -} - -export function GetDirections({ - selectedPlacesMap, - savedPlacesMap, - directionInformation, - setDirectionInformation, -}) { - // const [directionMatrix, setDirectionMatrix] = useState({}); - const [newDirection, setNewDirection] = useState({ - from: "", - to: "", - travelMode: "walking", - }); - const [loading, setLoading] = useState(false); - // { from, to, mode, routes: [{label, duration, distance, steps:[]}]} - useEffect(() => { - setNewDirection({ - from: "", - to: "", - travelMode: "walking", - }); - }, [selectedPlacesMap]); - const handleDirectionAdd = async () => { - if (newDirection.from === "" || newDirection.to === "") return; - // Fetch the direction between the two places from google maps - - setLoading(true); - const response = await mapApi.getDirections( - newDirection.from, - newDirection.to, - newDirection.travelMode - ); - if (response.success) { - // console.log(response.) - const routes = response.data.routes; - const newDirectionInfo = { ...directionInformation }; - const all_routes = []; - routes.forEach((route) => { - const steps = []; - route.legs[0].steps.forEach((step) => { - steps.push(step.html_instructions); - }); - all_routes.push({ - label: route.summary, - duration: route.legs[0].duration.text, - distance: route.legs[0].distance.text, - steps: steps, - }); - }); - if (newDirectionInfo[newDirection.from]) - newDirectionInfo[newDirection.from][newDirection.to] = { - ...newDirectionInfo[newDirection.from][newDirection.to], - [newDirection.travelMode]: { - routes: all_routes, - showSteps: false, - }, - }; - else { - newDirectionInfo[newDirection.from] = { - [newDirection.to]: { - [newDirection.travelMode]: { - routes: all_routes, - showSteps: false, - }, - }, - }; - } - setDirectionInformation(newDirectionInfo); - } - setLoading(false); - }; - return ( - <> - {Object.keys(directionInformation).length > 0 && ( -
-
-

- From -

-

- To -

-

- Mode -

-

- Routes -

-

- Steps -

-
- - {Object.keys(directionInformation).map((from_id, index) => ( -
-

- {savedPlacesMap[from_id].name || - selectedPlacesMap[from_id].alias} -

-
- {Object.keys(directionInformation[from_id]).map( - (to_id, index1) => ( -
- {Object.keys( - directionInformation[from_id][ - to_id - ] - ).map((mode, index2) => ( - <> - - - ))} - {Object.keys( - directionInformation[from_id] - ).length > - index1 + 1 && ( -
- )} -
- ) - )} -
-
- ))} -
- )} - - { -
-
-
- - - From - - - -
-
- - - To - - - -
-
- -
- - - Travel Mode - - - -
- -
- } - > - Add ($) - -
-
- } - - ); -} -export default function DirectionInformation({ - selectedPlacesMap, - savedPlacesMap, - directionInformation, - setDirectionInformation, -}) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
-
-

- Direction Information -

-

- Routes from one place to another -

-
- -
- ); -} diff --git a/src/app/old-home/DistanceInformation.jsx b/src/app/old-home/DistanceInformation.jsx deleted file mode 100644 index 5591202..0000000 --- a/src/app/old-home/DistanceInformation.jsx +++ /dev/null @@ -1,399 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import mapApi from "@/api/mapApi"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { Select, MenuItem, Button, TextField, IconButton } from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faTrashCan } from "@fortawesome/free-solid-svg-icons"; -import { LoadingButton } from "@mui/lab"; -import { Add } from "@mui/icons-material"; - -export function CalculateDistance({ - selectedPlacesMap, - savedPlacesMap, - distanceMatrix, - setDistanceMatrix, -}) { - const [newDistance, setNewDistance] = useState({ - from: [], - to: [], - travelMode: "walking", - }); - const [loading, setLoading] = useState(false); - - useEffect(() => { - setNewDistance({ - from: [], - to: [], - travelMode: "walking", - }); - }, [selectedPlacesMap]); - - const handleDistanceAdd = async () => { - console.log(newDistance); - if (newDistance.from.length === 0 || newDistance.to.length === 0) - return; - setLoading(true); - // Fetch the distance between the two places from google maps - const response = await mapApi.getDistance( - newDistance.from, - newDistance.to, - newDistance.travelMode - ); - if (response.success) { - console.log(response.data.matrix); - const origin = newDistance.from; - const destination = newDistance.to; - const matrix = response.data.matrix; - const newDistanceMatrix = { ...distanceMatrix }; - for (let i = 0; i < origin.length; i++) { - const o = origin[i]; - for (let j = 0; j < destination.length; j++) { - const d = destination[j]; - if (o === d) { - } else if (matrix[i][j].duration && matrix[i][j].distance) { - console.log(matrix[i][j]); - if (newDistanceMatrix[o]) - newDistanceMatrix[o][d] = { - ...newDistanceMatrix[o][d], - [newDistance.travelMode]: { - duration: matrix[i][j].duration.text, - distance: matrix[i][j].distance.text, - }, - }; - else { - newDistanceMatrix[o] = { - [d]: { - [newDistance.travelMode]: { - duration: matrix[i][j].duration.text, - distance: matrix[i][j].distance.text, - }, - }, - }; - } - } - } - } - setDistanceMatrix(newDistanceMatrix); - } - setNewDistance((prev) => ({ - from: [], - to: [], - travelMode: prev.travelMode, - })); - setLoading(false); - }; - - return ( - <> - {Object.keys(distanceMatrix).length > 0 && ( -
-
-

- From -

-

- To -

-

- Mode -

-

- Distance -

-

- Duration -

-
- - {Object.keys(distanceMatrix).map((from_id, index) => ( -
-

- {savedPlacesMap[from_id].name} -

-
- {Object.keys(distanceMatrix[from_id]).map( - (to_id, index1) => ( -
- {Object.keys( - distanceMatrix[from_id][to_id] - ).map((mode, index2) => ( - <> -
-

- { - savedPlacesMap[ - to_id - ].name - } -

-

- {mode} -

-

- { - distanceMatrix[ - from_id - ][to_id][mode] - .distance - } -

-

- { - distanceMatrix[ - from_id - ][to_id][mode] - .duration - } -

- { - const newDistanceMatrix = - { - ...distanceMatrix, - }; - delete newDistanceMatrix[ - from_id - ][to_id][mode]; - if ( - Object.keys( - newDistanceMatrix[ - from_id - ][to_id] - ).length === - 0 - ) - delete newDistanceMatrix[ - from_id - ][to_id]; - if ( - Object.keys( - newDistanceMatrix[ - from_id - ] - ).length === - 0 - ) - delete newDistanceMatrix[ - from_id - ]; - setDistanceMatrix( - newDistanceMatrix - ); - }} - > -
- -
-
-
- - ))} - {Object.keys( - distanceMatrix[from_id] - ).length > - index1 + 1 && ( -
- )} -
- ) - )} -
-
- ))} -
- )} - -
-
-
- - - From - - - -
-
- - - To - - - -
-
- -
- - - Travel Mode - - - -
- -
- } - loading={loading} - loadingPosition="start" - > - Add ($) - -
-
- - ); -} -export default function DistanceInformation({ - selectedPlacesMap, - savedPlacesMap, - distanceMatrix, - setDistanceMatrix, -}) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
-
-

- Distance Information -

-

- Distance and Duration from one place to another -

-
- -
- ); -} diff --git a/src/app/old-home/Evaluation.jsx b/src/app/old-home/Evaluation.jsx deleted file mode 100644 index d02ab5f..0000000 --- a/src/app/old-home/Evaluation.jsx +++ /dev/null @@ -1,93 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; - -export default function Evaluation({ queries }) { - const [result, setResult] = useState({}); - - useEffect(() => { - const tmp = {}; - let valid_questions = 0; - queries.forEach((query) => { - if (query.context !== "" && query.answer.correct !== -1) { - valid_questions++; - - query.evaluation?.forEach((e) => { - if (!tmp[e.model]) { - tmp[e.model] = { - correct: 0, - invalid: 0, - accuracy: 0, - wrong: 0, - }; - } - if (e.verdict === "right") { - tmp[e.model] = { - ...tmp[e.model], - correct: tmp[e.model]?.correct - ? tmp[e.model].correct + 1 - : 1, - }; - } else if (e.verdict == "invalid") { - console.log("Invalid question"); - tmp[e.model] = { - ...tmp[e.model], - invalid: tmp[e.model]?.invalid - ? tmp[e.model].invalid + 1 - : 1, - }; - } else { - tmp[e.model] = { - ...tmp[e.model], - wrong: tmp[e.model]?.wrong - ? tmp[e.model].wrong + 1 - : 1, - }; - } - console.log(query.id, tmp[e.model], e.model); - tmp[e.model].accuracy = - (tmp[e.model].correct * 100.0) / valid_questions; - }); - } - }); - setResult(tmp); - console.log(result); - }, [queries]); - - return ( -
-
-

Evaluation

-
-
-
-

Model

-

Accuracy

-

Correct

-

Wrong

-

No Answer

-
-
-
- {Object.keys(result).map((key, index) => ( -
-

{key}

-

- {parseFloat(result[key].accuracy).toFixed(2)} % -

-

- {result[key].correct} -

-

- {result[key].wrong} -

-

- {result[key].invalid} -

-
- ))} -
-
-
- ); -} diff --git a/src/app/old-home/HybridSearch.jsx b/src/app/old-home/HybridSearch.jsx deleted file mode 100644 index 78b2b06..0000000 --- a/src/app/old-home/HybridSearch.jsx +++ /dev/null @@ -1,475 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import placeApi from "@/api/placeApi"; -import mapApi from "@/api/mapApi"; -import { - Select, - MenuItem, - Button, - TextField, - Divider, - Typography, -} from "@mui/material"; -import _ from "lodash"; - -import { LoadingButton } from "@mui/lab"; -import { Add, Clear, Download, Search, Start } from "@mui/icons-material"; -import Fuse from "fuse.js"; -import { useCallback } from "react"; -import { Chip, CircularProgress, InputAdornment } from "@mui/material"; -import debounce from "lodash/debounce"; - -export const AutocompleteSearchBox = ({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, -}) => { - const [addPlace, setAddPlace] = useState(""); - const [search, setSearch] = useState(""); - const [results, setResults] = useState([]); - const [selectedPlace, setSelectedPlace] = useState(null); - const [loading, setLoading] = useState(false); - const [filteredPlaces, setFilteredPlaces] = useState([]); - const [buttonLoading, setButtonLoading] = useState(false); - const [fetched, setFetched] = useState(false); - const fetchPlaces = async () => { - console.log("Fetching places"); - setButtonLoading(true); - try { - const res = await placeApi.getPlaces(); - if (res.success) { - // create a map for easy access - const newSavedPlacesMap = {}; - res.data.forEach((e) => { - newSavedPlacesMap[e.place_id] = e; - }); - setSavedPlacesMap(newSavedPlacesMap); - setFetched(true); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - setButtonLoading(false); - }; - - useEffect(() => { - if (process.env.NODE_ENV === "production") { - fetchPlaces(); - } - }, []); - - const handleSearch = async (event) => { - event.preventDefault(); - if (search === "") return; - setLoading(true); - try { - const response = await mapApi.search(search); - if (response.success) { - setResults(response.data.results); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - setLoading(false); - }; - - const handleSelectPlace = (place) => { - if (selectedPlace === place) { - setSelectedPlace(null); - } else { - setSelectedPlace(place); - } - }; - - // Debounced search function - const debouncedSearch = React.useCallback( - _.debounce((query) => { - // Your search logic here, for example: - // const fuse = new Fuse(Object.values(savedPlacesMap), { - // keys: ["name", "formatted_address"], - // threshold: 0.3, - // // distance: 100, - // ignoreLocation: true, - // }); - // const result = fuse.search(query); - // const filteredPlaces = result.map((item) => item.item); - // setFilteredPlaces(filteredPlaces); - - setFilteredPlaces(() => { - const startsWithQuery = []; - const nameIncludesQuery = []; - const addressIncludesQuery = []; - - Object.values(savedPlacesMap).forEach((place) => { - const lowerCaseName = place.name.toLowerCase(); - const lowerCaseAddress = - place.formatted_address.toLowerCase(); - const lowerCaseQuery = query.toLowerCase(); - - if (lowerCaseName.startsWith(lowerCaseQuery)) { - startsWithQuery.push(place); - } else if (lowerCaseName.includes(lowerCaseQuery)) { - nameIncludesQuery.push(place); - } else if (lowerCaseAddress.includes(lowerCaseQuery)) { - addressIncludesQuery.push(place); - } - }); - - console.log("Starts With Query:", startsWithQuery); - console.log("Name Includes Query:", nameIncludesQuery); - console.log("Address Includes Query:", addressIncludesQuery); - - return [ - ...startsWithQuery, - ...nameIncludesQuery, - ...addressIncludesQuery, - ]; - }); - // setFilteredPlaces( - // Object.values(savedPlacesMap).filter( - // (place) => - // place.name.toLowerCase().startsWith(query.toLowerCase()) - // // || - // // place.formatted_address - // // .toLowerCase() - // // .includes(search.toLowerCase()) - // ) - // ); - }, 300), - [savedPlacesMap] - ); // Adjust debounce time as needed - - const handleFuzzySearch = async () => { - // Convert savedPlacesMap object values to an array - const placesArray = Object.values(savedPlacesMap); - - // Fuse.js options - const options = { - // Properties to search in - keys: ["name", "formatted_address"], - // // Other options like threshold can be added here - threshold: 0.2, // Lower this to make the search stricter, or increase for more fuzziness - // distance: 100, // Increase this to allow for more flexibility in term location - ignoreLocation: true, // Consider setting to true for more lenient matches - // // You can adjust these values based on testing to find what works best for your data - // findAllMatches: true, - }; - - // Create a new Fuse instance with the places array and options - const fuse = new Fuse(placesArray, options); - - // Use Fuse to search - const result = fuse.search(search); - - // Map the search result to get the original place objects - const filteredPlaces = result.map((item) => item.item); - - // Update state with the filtered places - setFilteredPlaces(filteredPlaces); - }; - - useEffect(() => { - if (search) { - debouncedSearch(search); - // setFilteredPlaces( - // Object.values(savedPlacesMap).filter( - // (place) => - // place.name.toLowerCase().includes(search.toLowerCase()) - // // || - // // place.formatted_address - // // .toLowerCase() - // // .includes(search.toLowerCase()) - // ) - // ); - } else { - // Handle the case when search is cleared - setFilteredPlaces(Object.values(savedPlacesMap)); - } - }, [search, debouncedSearch]); - - const handleAddSave = async () => { - console.log("Saved: ", selectedPlace); - // Save the selected place as needed - const place_id = selectedPlace["place_id"]; - let details = selectedPlacesMap[place_id]; - if (details === undefined) { - details = savedPlacesMap[place_id]; - if (details === undefined) { - const res = await mapApi.getDetails(place_id); - if (res.success) { - details = res.data.result; - setSavedPlacesMap((prev) => ({ - ...prev, - [place_id]: details, - })); - } else { - console.error("Error fetching data: ", res.error); - return; - } - } - handleAdd(details); - } else { - console.log("Already saved: ", details); - } - setSelectedPlace(null); - return details; - }; - - const handleAdd = (details) => { - const place_id = details["place_id"]; - if (place_id === "" || selectedPlacesMap[place_id]) return; - setSelectedPlacesMap((prev) => ({ - ...prev, - [place_id]: { - alias: "", - selectedAttributes: ["formatted_address"], - attributes: Object.keys(details).filter( - (key) => details[key] !== null - ), - }, - })); - }; - - return ( -
-
-
- setSearch(e.target.value)} - /> -
-
-
- } - loadingPosition="start" - > - Search ($) - -
- -
- -
-
-
- -
- {/* Column 1 */} -
-
-
-
- Places found in the Database -
-
- {filteredPlaces - .sort((a, b) => { - // Only sort if search is an empty string - if (search === "") { - // Place null values at the end - if (a.last_updated === null) - return 1; - if (b.last_updated === null) - return -1; - - // Sort in descending order - return ( - new Date(b.last_updated) - - new Date(a.last_updated) - ); - } - // If search is not empty, do not sort - return 0; - }) - .map((place, index) => ( -
  • - -
  • - ))} - - {filteredPlaces.length === 0 && ( -
    - No places found -
    - )} -
    -
    -
    - -
    -
    - {!fetched && ( -
    - { - fetchPlaces(); - }} - loading={buttonLoading} - endIcon={} - loadingPosition="end" - size="large" - > - Previous Places - -
    - )} -
    - - {/* Column 2 */} -
    -
    -
      -
      - Places fetched from Google Map -
      -
      - {results.map((place, index) => ( -
    • - -
    • - ))} - {results.length === 0 && ( -
      - No places found -
      - )} -
      -
    -
    - -
    -
    -
    -
    -
    - ); -}; - -export default function HybridSearch({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, -}) { - // const [search, setSearch] = useState(""); - - return ( -
    -
    -

    - Add places in the Context -

    -

    - Search for a place from google map or our database -

    -
    -
    - -
    -
    - ); -} diff --git a/src/app/old-home/Login.jsx b/src/app/old-home/Login.jsx deleted file mode 100644 index 4b626e8..0000000 --- a/src/app/old-home/Login.jsx +++ /dev/null @@ -1,195 +0,0 @@ -import React, { useState, useEffect } from "react"; -import AuthService from "@/services/authService"; -import { FormControl, InputLabel, OutlinedInput, Button } from "@mui/material"; -import EyeIcon from "@/components/Icons/EyeIcon"; -import { LoadingButton } from "@mui/lab"; -import { showMessage } from "./home"; - -const MuiTextField = (props) => { - return ( -
    - - - {props.label} - - - -
    - ); -}; - -const MuiPasswordField = (props) => { - const [showPassword, setShowPassword] = useState(false); - return ( -
    - - - {props.label} - - - 0} - showPassword={showPassword} - setShowPassword={setShowPassword} - /> -
    - } - /> - -
    - ); -}; -const Login = () => { - const [username, setUserName] = useState(""); - const [password, setPassword] = useState(""); - const [loggingIn, setLoggingIn] = useState(false); - - const handleSubmit = async (e) => { - e.preventDefault(); - if (!loggingIn) { - // setLoading(true); - setLoggingIn(true); - - const res = await AuthService.login({ - username: username, - password: password, - }); - if (res.success) { - // navigate("/"); - } else { - // setLoading(false); - // showMessage("Invalid Credentials", "error"); - } - } - }; - - useEffect(() => { - // setLoading(false); - }, []); - return ( - <> -
    -
    -
    -
    -

    - Sign in to your account -

    -
    - - setUserName(e.target.value) - } - value={username} - /> - - setPassword(e.target.value) - } - value={password} - /> - - Sign in - - -
    -
    -
    -
    - - ); -}; - -export default Login; diff --git a/src/app/old-home/NearbyInformation.jsx b/src/app/old-home/NearbyInformation.jsx deleted file mode 100644 index 2e77eb6..0000000 --- a/src/app/old-home/NearbyInformation.jsx +++ /dev/null @@ -1,482 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import placeApi from "@/api/placeApi"; -import mapApi from "@/api/mapApi"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { - Select, - MenuItem, - Button, - TextField, - IconButton, - Typography, -} from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faChevronDown, - faChevronUp, - faTrashCan, - faAdd, -} from "@fortawesome/free-solid-svg-icons"; -import placeTypes from "@/database/types.json"; -import Autocomplete from "@mui/material/Autocomplete"; -import { LoadingButton } from "@mui/lab"; -import { Add } from "@mui/icons-material"; -import { convertFromSnake } from "@/services/utils"; - -function NearbyCard({ - index2, - selectedPlacesMap, - savedPlacesMap, - setSavedPlacesMap, - nearbyPlacesMap, - setNearbyPlacesMap, - setSelectedPlacesMap, - place_id, - e, -}) { - const [expanded, setExpanded] = useState(false); - - const handleAddSave = async (place_id) => { - let details = selectedPlacesMap[place_id]; - if (details === undefined) { - details = savedPlacesMap[place_id]; - if (details === undefined) { - const res = await mapApi.getDetails(place_id); - if (res.success) { - details = res.data.result; - setSavedPlacesMap((prev) => ({ - ...prev, - [place_id]: details, - })); - } else { - console.error("Error fetching data: ", res.error); - return; - } - } - handleAdd(details); - } else { - console.log("Already saved: ", details); - } - return details; - }; - - const handleAdd = (details) => { - const place_id = details["place_id"]; - if (place_id === "" || selectedPlacesMap[place_id]) return; - setSelectedPlacesMap((prev) => ({ - ...prev, - [place_id]: { - alias: "", - selectedAttributes: ["formatted_address"], - attributes: Object.keys(details).filter( - (key) => details[key] !== null - ), - }, - })); - }; - - return ( -
    -
    -

    - {savedPlacesMap[place_id].name || - selectedPlacesMap[place_id].alias} -

    -

    - {e.type === "any" ? e.keyword : e.type} -

    - {/*

    {e.keyword || "N/A"}

    */} -

    - {e.hasRadius ? e.radius + " m" : "Distance"} -

    - {/*

    - {e.places.length} -

    */} - { - const newNearbyPlacesMap = { - ...nearbyPlacesMap, - }; - newNearbyPlacesMap[place_id].splice(index2, 1); - - if (newNearbyPlacesMap[place_id].length === 0) - delete newNearbyPlacesMap[place_id]; - setNearbyPlacesMap(newNearbyPlacesMap); - }} - > -
    - -
    -
    - setExpanded((prev) => !prev)} - > -
    - -
    -
    -
    - {expanded && ( -
    - {e.places.map((place, index3) => ( -
    -
    - { - const newNearbyPlacesMap = { - ...nearbyPlacesMap, - }; - newNearbyPlacesMap[place_id][ - index2 - ].places[index3].selected = - event.target.checked; - setNearbyPlacesMap(newNearbyPlacesMap); - }} - /> -

    - {place.name} - {place.formatted_address} -

    - { - handleAddSave(place.place_id); - }} - > - - -
    - {index3 < e.places.length - 1 && ( -
    - )} -
    - ))} -
    - )} -
    - ); -} - -export function NearbyInfo({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, - nearbyPlacesMap, - setNearbyPlacesMap, -}) { - // place_id -> place - const [newNearbyPlaces, setNewNearbyPlaces] = useState({ - location: "", - type: "", - keyword: "", - radius: 1, - rankBy: "distance", - hasRadius: false, - list: [], - }); - const [nearbyPlacesResults, setNearbyPlacesResults] = useState([]); // list of places from nearby search - const [loading, setLoading] = useState(false); - useEffect(() => { - setNewNearbyPlaces({ - location: "", - type: "", - keyword: "", - radius: 1, - rankBy: "distance", - hasRadius: false, - list: [], - }); - setNearbyPlacesResults([]); - }, [selectedPlacesMap]); - - const searchNearbyPlaces = async () => { - console.log(newNearbyPlaces); - if (newNearbyPlaces.location === "" || newNearbyPlaces.type === "") - return; - - setLoading(true); - try { - const loc = - savedPlacesMap[newNearbyPlaces.location].geometry.location; - const lat = typeof loc.lat === "function" ? loc.lat() : loc.lat; - const lng = typeof loc.lng === "function" ? loc.lng() : loc.lng; - const response = await mapApi.getNearby({ - location: newNearbyPlaces.location, - lat, - lng, - radius: newNearbyPlaces.radius, - type: newNearbyPlaces.type, - keyword: newNearbyPlaces.keyword, - rankBy: newNearbyPlaces.hasRadius ? "prominence" : "distance", - }); - if (response.success) { - const places = response.data.results; - console.log("Nearby Places: ", response.data); - const newNearbyPlacesMap = { ...nearbyPlacesMap }; - if ( - newNearbyPlacesMap[newNearbyPlaces.location] === undefined - ) { - newNearbyPlacesMap[newNearbyPlaces.location] = []; - } - - const placesWithSelection = places.map((place) => ({ - selected: true, - place_id: place.place_id, - name: place.name, - formatted_address: place.vicinity, - })); - - if (!placeTypes.includes(newNearbyPlaces.type)) { - newNearbyPlaces.keyword = newNearbyPlaces.type; - } - newNearbyPlacesMap[newNearbyPlaces.location].push({ - type: placeTypes.includes(newNearbyPlaces.type) - ? newNearbyPlaces.type - : "any", - places: placesWithSelection, - keyword: placeTypes.includes(newNearbyPlaces.type) - ? "" - : newNearbyPlaces.keyword, - radius: newNearbyPlaces.radius, - hasRadius: newNearbyPlaces.hasRadius, - rankBy: newNearbyPlaces.rankBy, - }); - - setNearbyPlacesMap(newNearbyPlacesMap); - setLoading(false); - setNearbyPlacesResults(placesWithSelection); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - setLoading(false); - }; - return ( - <> - {Object.keys(nearbyPlacesMap).length > 0 && ( -
    -
    -

    - Location -

    -

    - Type -

    - {/*

    - Keyword -

    */} -

    - Rank By/Radius -

    - {/*

    - Count -

    */} -
    - - {Object.keys(nearbyPlacesMap).map((place_id, index1) => ( -
    - {nearbyPlacesMap[place_id].map((e, index2) => ( - - ))} -
    - ))} -
    - )} - -
    -
    - - - Location - - - -
    - convertFromSnake(option)} - onChange={(e, newValue) => { - // console.log("newValue: ", newValue); - setNewNearbyPlaces((prev) => ({ - ...prev, - type: newValue, - })); - }} - renderInput={(params) => ( - { - // console.log("newValue: ", newValue); - setNewNearbyPlaces((prev) => ({ - ...prev, - type: e.target.value, - })); - }} - /> - )} - /> -
    -
    - - setNewNearbyPlaces((prev) => ({ - ...prev, - hasRadius: false, - })) - } - /> - Rank By Distance -
    - -
    - - setNewNearbyPlaces((prev) => ({ - ...prev, - hasRadius: true, - })) - } - /> - { - setNewNearbyPlaces((prev) => ({ - ...prev, - radius: event.target.value, - })); - }} - type="number" - // input={} - // MenuProps={MenuProps} - /> -
    -
    -
    - } - loading={loading} - loadingPosition="start" - > - Add ($) - -
    -
    - - ); -} -export default function NearbyInformation({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, - nearbyPlacesMap, - setNearbyPlacesMap, -}) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
    -
    -

    - Nearby Places -

    -

    - Nearby POIs of a given location -

    -
    - -
    - ); -} diff --git a/src/app/old-home/OfflineSearch.jsx b/src/app/old-home/OfflineSearch.jsx deleted file mode 100644 index 9341f95..0000000 --- a/src/app/old-home/OfflineSearch.jsx +++ /dev/null @@ -1,120 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import { Select, MenuItem, Button, TextField } from "@mui/material"; - -const AutocompleteSearchBox = ({ savedPlacesMap, addPlace, setAddPlace }) => { - const [search, setSearch] = useState(""); - - const filteredPlaces = Object.values(savedPlacesMap).filter( - (place) => - place.name.toLowerCase().includes(search.toLowerCase()) || - place.formatted_address.toLowerCase().includes(search.toLowerCase()) - ); - return ( - <> -
    - setSearch(e.target.value)} - /> - -
    -
    - {filteredPlaces.map((place, index) => ( -
  • - -
  • - ))} -
    - - ); -}; - -export default function OfflineSearch({ - savedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, -}) { - const [addPlace, setAddPlace] = useState(""); - const handleAdd = (place_id) => { - // Don't add if already added - if (place_id === "") return; - - const newSelectedPlacesMap = { ...selectedPlacesMap }; - newSelectedPlacesMap[place_id] = { - alias: "", - selectedAttributes: ["formatted_address"], - attributes: Object.keys(savedPlacesMap[place_id]).filter( - (key) => savedPlacesMap[place_id][key] !== null - ), - }; - setSelectedPlacesMap(newSelectedPlacesMap); - - setAddPlace(""); - }; - return ( -
    -
    -

    Offline: Choose a place

    -

    - Choose a place from the database -

    -
    - - {addPlace !== "" && ( -
    - {/* */} - - -
    - )} -
    - ); -} diff --git a/src/app/old-home/OnlineSearch.jsx b/src/app/old-home/OnlineSearch.jsx deleted file mode 100644 index 242c2ec..0000000 --- a/src/app/old-home/OnlineSearch.jsx +++ /dev/null @@ -1,221 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import placeApi from "@/api/placeApi"; -import mapApi from "@/api/mapApi"; -import { Select, MenuItem, Button, TextField } from "@mui/material"; - -export default function OnlineSearch({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - setSelectedPlacesMap, - setPoisMap, -}) { - const [search, setSearch] = useState(""); - const [results, setResults] = useState([]); - - const [selectedPlace, setSelectedPlace] = useState(null); - - const handleSelectPlace = (place) => { - if (selectedPlace === place) { - setSelectedPlace(null); - } else { - setSelectedPlace(place); - } - }; - - const handleSearch = async (event) => { - event.preventDefault(); - if (search === "") return; - try { - const response = await mapApi.search(search); - if (response.success) { - setResults(response.data.results); - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - - const handleSave = async () => { - try { - const response = await mapApi.getDetails(selectedPlace["place_id"]); - if (response.success) { - const res = await placeApi.createPlace(response.data.result); - if (res.success) { - const newSavedPlacesMap = { ...savedPlacesMap }; - newSavedPlacesMap[res.data[0].place_id] = res.data[0]; - setSavedPlacesMap(newSavedPlacesMap); - } - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - - const handleAddSave = async () => { - console.log("Saved: ", selectedPlace); - // Save the selected place as needed - try { - const response = await mapApi.getDetails(selectedPlace["place_id"]); - if (response.success) { - const res = await placeApi.createPlace(response.data.result); - if (res.success) { - const newSavedPlacesMap = { ...savedPlacesMap }; - newSavedPlacesMap[res.data[0].place_id] = res.data[0]; - setSavedPlacesMap(newSavedPlacesMap); - - const newSelectedPlacesMap = { ...selectedPlacesMap }; - newSelectedPlacesMap[res.data[0].place_id] = { - alias: "", - selectedAttributes: ["formatted_address"], - attributes: Object.keys(res.data[0]).filter( - (e) => res.data[0][e] !== null - ), - }; - setSelectedPlacesMap(newSelectedPlacesMap); - - setSelectedPlace(null); - return res.data[0]; - } - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - - const handleAddAll = async () => { - try { - setPoisMap((prev) => [ - ...prev, - { - query: search, - places: results.map((place) => ({ - ...place, - selected: true, - })), - }, - ]); - - const newSavedPlacesMap = { ...savedPlacesMap }; - for (const place of results) { - if (newSavedPlacesMap[place.place_id] === undefined) { - try { - const response = await mapApi.getDetails( - place.place_id - ); - if (response.success) { - const res = await placeApi.createPlace( - response.data.result - ); - if (res.success) { - newSavedPlacesMap[place.place_id] = res.data[0]; - console.log("saved: ", res.data[0].place_id); - } - } - } catch (error) { - console.error(error); - } - } - } - } catch (error) { - console.error("Error fetching data: ", error); - } - }; - - return ( -
    -
    -

    - Online: Search for a place -

    -

    - Search for a place and save it to the database -

    -
    -
    -
    - setSearch(e.target.value)} - /> - -
    - {results.length > 0 && ( -
    - - {/* */} -
    - )} - {/*

    */} -
      - {results.map((place, index) => ( -
    • - -
    • - ))} -
    -
    - {selectedPlace && ( -
    - - {/* */} -
    - )} -
    - ); -} diff --git a/src/app/old-home/POI.jsx b/src/app/old-home/POI.jsx deleted file mode 100644 index f0411f7..0000000 --- a/src/app/old-home/POI.jsx +++ /dev/null @@ -1,384 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import placeApi from "@/api/placeApi"; -import mapApi from "@/api/mapApi"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { Select, MenuItem, Button, TextField, IconButton } from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faChevronDown, - faChevronUp, - faTrashCan, - faAdd, -} from "@fortawesome/free-solid-svg-icons"; -import placeTypes from "@/database/types.json"; -import Autocomplete from "@mui/material/Autocomplete"; -import { LoadingButton } from "@mui/lab"; -import { Add } from "@mui/icons-material"; -import { convertFromSnake } from "@/services/utils"; - -function POICard({ - selectedPlacesMap, - savedPlacesMap, - setSavedPlacesMap, - poi, - poisMap, - setPoisMap, - index2, - place_id, - setSelectedPlacesMap, -}) { - const [expanded, setExpanded] = useState(false); - const handleAddSave = async (place_id) => { - let details = selectedPlacesMap[place_id]; - if (details === undefined) { - details = savedPlacesMap[place_id]; - if (details === undefined) { - const res = await mapApi.getDetails(place_id); - if (res.success) { - details = res.data.result; - setSavedPlacesMap((prev) => ({ - ...prev, - [place_id]: details, - })); - } else { - console.error("Error fetching data: ", res.error); - return; - } - } - handleAdd(details); - } else { - console.log("Already saved: ", details); - } - return details; - }; - - const handleAdd = (details) => { - const place_id = details["place_id"]; - if (place_id === "" || selectedPlacesMap[place_id]) return; - setSelectedPlacesMap((prev) => ({ - ...prev, - [place_id]: { - alias: "", - selectedAttributes: ["formatted_address"], - attributes: Object.keys(details).filter( - (key) => details[key] !== null - ), - }, - })); - }; - return ( -
    -
    -

    - {savedPlacesMap[place_id].name || - selectedPlacesMap[place_id].alias} -

    -

    {poi.type}

    -

    - { - poisMap[place_id][index2].places.filter( - (place) => place.selected - ).length - } -

    - { - const newPoisMap = { - ...poisMap, - }; - newPoisMap[place_id].splice(index2, 1); - if (newPoisMap[place_id].length === 0) - delete newPoisMap[place_id]; - setPoisMap(newPoisMap); - }} - > -
    - -
    -
    - setExpanded((prev) => !prev)} - > -
    - -
    -
    -
    - - {expanded && ( -
    - {poi.places.map((place, index3) => ( -
    -
    - { - const newPoisMap = { ...poisMap }; - newPoisMap[place_id][index2].places[ - index3 - ].selected = event.target.checked; - setPoisMap(newPoisMap); - }} - /> -

    - {place.name} - {place.formatted_address} -

    - { - handleAddSave(place.place_id); - }} - > - - -
    - {index3 < poi.places.length - 1 && ( -
    - )} -
    - ))} -
    - )} -
    - ); -} - -export function DiscoverArea({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - poisMap, - setSelectedPlacesMap, - setPoisMap, -}) { - const [newPois, setNewPois] = useState({ location: "", type: "" }); - const [loading, setLoading] = useState(false); - // useEffect(() => { - // console.log(selectedPlacesMap); - // }, [selectedPlacesMap]); - - const searchInsidePlaces = async () => { - if (newPois.location === "" || newPois.type === "") return; - - setLoading(true); - try { - const res = await mapApi.getInside({ - location: newPois.location, - type: newPois.type, - }); - if (res.success) { - const places = res.data.results; - const newPoisMap = { ...poisMap }; - if (newPoisMap[newPois.location] === undefined) { - newPoisMap[newPois.location] = []; - } - - const placesWithSelection = places.map((place) => ({ - selected: true, - place_id: place.place_id, - name: place.name, - formatted_address: place.formatted_address, - })); - - newPoisMap[newPois.location].push({ - type: newPois.type, - places: placesWithSelection, - }); - - setPoisMap(newPoisMap); - setLoading(false); - // const newSavedPlacesMap = { ...savedPlacesMap }; - // for (const place of results) { - // if (newSavedPlacesMap[place.place_id] === undefined) { - // try { - // const res2 = await mapApi.getDetails( - // place.place_id - // ); - // if (res2.success) { - // newSavedPlacesMap[place.place_id] = - // res2.data[0]; - // console.log("saved: ", res.data[0].place_id); - // } - // } catch (error) { - // console.error(error); - // } - // } - // } - // setSavedPlacesMap(newSavedPlacesMap); - } - } catch (error) { - // console.error("Error fetching data: ", error); - } - setLoading(false); - }; - - return ( - <> - {Object.keys(poisMap).length > 0 && ( -
    -
    -

    - Location -

    -

    - Type -

    - -

    - Count -

    -
    - {Object.keys(poisMap).map((place_id, index1) => ( -
    - {poisMap[place_id].map((poi, index2) => ( - - ))} -
    - ))} -
    - )} -
    -
    - - - Location - - - -
    -
    - convertFromSnake(option)} - onChange={(e, newValue) => { - setNewPois((prev) => ({ - ...prev, - type: newValue, - })); - }} - renderInput={(params) => ( - { - setNewPois((prev) => ({ - ...prev, - type: e.target.value, - })); - }} - /> - )} - /> -
    - -
    - } - loading={loading} - loadingPosition="start" - > - Add ($) - -
    -
    - - ); -} -export default function POI({ - savedPlacesMap, - setSavedPlacesMap, - selectedPlacesMap, - poisMap, - setSelectedPlacesMap, - setPoisMap, -}) { - return ( - // Object.keys(selectedPlacesMap).length > 0 && -
    -
    -

    - Places in an Area -

    -

    - Results of the Points of Interest search -

    -
    - -
    - ); -} diff --git a/src/app/old-home/PlaceInformation.jsx b/src/app/old-home/PlaceInformation.jsx deleted file mode 100644 index c302df3..0000000 --- a/src/app/old-home/PlaceInformation.jsx +++ /dev/null @@ -1,212 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { Select, MenuItem, Button, TextField, IconButton } from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import { convertFromSnake } from "@/services/utils"; - -export default function PlaceInformation({ - selectedPlacesMap, - setSelectedPlacesMap, - savedPlacesMap, - distanceMatrix, - setDistanceMatrix, - directionInformation, - setDirectionInformation, - nearbyPlacesMap, - setNearbyPlacesMap, - poisMap, - setPoisMap, -}) { - const deletePlaceFromDistanceMatrix = (place_id) => { - const newDistanceMatrix = { ...distanceMatrix }; - delete newDistanceMatrix[place_id]; - Object.keys(newDistanceMatrix).forEach((key) => { - delete newDistanceMatrix[key][place_id]; - }); - setDistanceMatrix(newDistanceMatrix); - }; - - const deletePlaceFromDirections = (place_id) => { - const newDirectionInformation = { ...directionInformation }; - delete newDirectionInformation[place_id]; - - Object.keys(newDirectionInformation).forEach((key) => { - delete newDirectionInformation[key][place_id]; - }); - setDirectionInformation(newDirectionInformation); - }; - - const deletePlaceFromNearbyPlaces = (place_id) => { - const newNearbyPlacesMap = { ...nearbyPlacesMap }; - delete newNearbyPlacesMap[place_id]; - setNearbyPlacesMap(newNearbyPlacesMap); - }; - - const deletePlaceFromPois = (place_id) => { - const newPoisMap = { ...poisMap }; - delete newPoisMap[place_id]; - setPoisMap(newPoisMap); - }; - - const deletePlace = (place_id) => { - deletePlaceFromDistanceMatrix(place_id); - deletePlaceFromDirections(place_id); - deletePlaceFromNearbyPlaces(place_id); - deletePlaceFromPois(place_id); - const newSelectedPlacesMap = { ...selectedPlacesMap }; - delete newSelectedPlacesMap[place_id]; - setSelectedPlacesMap(newSelectedPlacesMap); - }; - - useEffect(() => { - console.log("Selected Places Map: ", selectedPlacesMap); - }, [selectedPlacesMap]); - return ( - Object.keys(selectedPlacesMap).length > 0 && ( -
    -
    -

    - Places Information -

    -

    - List of all places in the context -

    -
    -
    -
    - {/*
    -

    - Place -

    -

    - Attributes -

    -
    */} - - {Object.keys(selectedPlacesMap).map( - (place_id, index) => ( -
    -
    -

    - {/*

    {index + 1}

    */} - - {savedPlacesMap[place_id].name} - {" "} - ( - { - savedPlacesMap[place_id] - .formatted_address - } - ) - -
    - {/* { - const newSelectedPlacesMap = { - ...selectedPlacesMap, - }; - newSelectedPlacesMap[ - place_id - ].alias = event.target.value; - setSelectedPlacesMap( - newSelectedPlacesMap - ); - }} - /> */} -
    - - - - { - deletePlace(place_id); - }} - > -
    - -
    -
    -
    -
    - ) - )} -
    -
    -
    - ) - ); -} diff --git a/src/app/old-home/QueryCard.jsx b/src/app/old-home/QueryCard.jsx deleted file mode 100644 index b90ba0d..0000000 --- a/src/app/old-home/QueryCard.jsx +++ /dev/null @@ -1,556 +0,0 @@ -"use client"; - -import React, { use, useEffect, useState } from "react"; -import { - IconButton, - Button, - FormControl, - Select, - InputLabel, - OutlinedInput, - MenuItem, - Radio, - TextField, - Divider, -} from "@mui/material"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faChevronDown, - faChevronUp, - faPen, - faTrash, - faUser, -} from "@fortawesome/free-solid-svg-icons"; -import queryApi from "@/api/queryApi"; -import QueryFields from "./QueryFields"; -import dayjs from "dayjs"; -import { Clear, Save } from "@mui/icons-material"; -import mapApi from "@/api/mapApi"; - -export default function QueryCard({ - initQuery, - index, - setSelectedPlacesMap, - setDistanceMatrix, - setNearbyPlacesMap, - setCurrentInformation, - setDirectionInformation, - setSavedPlacesMap, - setContext, - context, - setContextJSON, - contextJSON, - handleDelete, - handleEdit, - setPoisMap, -}) { - const [expanded, setExpanded] = useState(false); - const [mode, setMode] = useState("view"); - const [flag, setFlag] = useState(false); - const [query, setQuery] = useState(initQuery); - const [contextExpanded, setContextExpanded] = useState(false); - const handleSave = async (place_id) => { - const res = await mapApi.getDetails(place_id); - if (res.success) { - const details = res.data.result; - setSavedPlacesMap((prev) => ({ - ...prev, - [place_id]: details, - })); - } else { - console.error("Error fetching data: ", res.error); - return; - } - }; - useEffect(() => { - setQuery(initQuery); - }, [initQuery]); - - useEffect(() => { - const invalid = query.evaluation?.find( - (e) => - e.model !== "mistralai/Mixtral-8x7B-Instruct-v0.1" && - e.verdict === "invalid" - ); - console.log(query.human); - if (invalid) { - setFlag(true); - } else { - setFlag(query.human.answer === 0); - } - }, [query]); - return ( -
    -
    -
    -

    - {" "} - # {query.id} -

    -
    - {query.classification} -
    -
    - -
    -

    - - {query.username} -

    - {mode == "view" && ( -
    - setExpanded((prev) => !prev)} - > -
    - -
    -
    -
    - )} -
    -
    - {mode === "edit" ? ( - { - handleEdit(new_query, index); - setMode("view"); - // window.location.reload(); - }} - initialQuery={query} - /> - ) : expanded ? ( -
    - {/*
    - - - Category - - - - -
    */} - -
    -
    -

    - {contextExpanded - ? "Hide Context" - : "Show Context"} -

    - - setContextExpanded((prev) => !prev) - } - > -
    - -
    -
    -
    - {contextExpanded && ( -
    -

    - Context (Template) -

    -

    - {query.context - .split("\n") - .map((line, index) => ( - - {/* {line} */} -

    - {/*
    */} - - ))} -

    -

    - Context (GPT) -

    -

    - {query.context_gpt - .split("\n") - .map((line, index) => ( - - {line} -
    -
    - ))} -

    -
    - )} -
    - -

    Question

    -

    {query.question}

    - -

    Options

    - {query.answer.type === "mcq" ? ( -
    - {query.answer.options.map( - (option, index) => - option !== "" && ( -
    - -

    - {option} -

    -
    - ) - )} -
    - ) : ( -

    {query.answer.correct}

    - )} - - {query.evaluation?.length > 0 && ( -
    -

    - Evaluation -

    -
    - {query.evaluation?.map((e, index) => ( -
    -

    - {e.model} -

    - {e.verdict == "invalid" ? ( -

    - {"Can't answer"} - {e.answer !== "" - ? "(" + e.answer + ")" - : ""} -

    - ) : e.verdict == "right" ? ( -

    - Correct -

    - ) : ( -

    - Wrong {"(" + e.answer + ")"} -

    - )} -
    - ))} -
    -
    - )} -
    -
    -

    - Human Annotation -

    -

    - - {query.human.username} -

    -
    -
    -
    - - - Correct Answer - - - - { - setQuery((prev) => ({ - ...prev, - human: { - ...prev.human, - explanation: e.target.value, - }, - })); - }} - fullWidth - label="Explanation" - size="small" - multiline - /> -
    - - -
    -
    -
    -
    - - {/*
    */} -
    - {/* */} - {/* */} - - {/* */} -
    -
    - ) : ( -

    {query.question}

    - )} -
    - ); -} diff --git a/src/app/old-home/QueryFields.jsx b/src/app/old-home/QueryFields.jsx deleted file mode 100644 index cb4efe9..0000000 --- a/src/app/old-home/QueryFields.jsx +++ /dev/null @@ -1,632 +0,0 @@ -"use client"; - -import React, { useEffect, useState } from "react"; -import queryApi from "@/api/queryApi"; -import gptApi from "@/api/gptApi"; -import FormControl from "@mui/material/FormControl"; -import InputLabel from "@mui/material/InputLabel"; -import OutlinedInput from "@mui/material/OutlinedInput"; -import { - FormLabel, - RadioGroup, - FormControlLabel, - Radio, - IconButton, - Button, - TextField, - Select, - MenuItem, - Card, -} from "@mui/material"; -import QueryCard from "./QueryCard"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faChevronDown, - faChevronUp, - faFloppyDisk, - faRobot, - faTrash, -} from "@fortawesome/free-solid-svg-icons"; -import { TextareaAutosize } from "@mui/base/TextareaAutosize"; -import { Clear, Refresh, Save } from "@mui/icons-material"; -import { LoadingButton } from "@mui/lab"; - -export default function QueryFields({ - contextJSON, - context, - initialQuery, - onSave, -}) { - const [expanded, setExpanded] = useState(true); - const init = { - question: "", - answer: { - type: "mcq", - options: ["", "", "", ""], - correct: -1, - }, - context: "", - context_json: {}, - context_gpt: "", - classification: "", - }; - const [query, setQuery] = useState(init); - const [translating, setTranslating] = useState(false); - const [newOption, setNewOption] = useState(""); - useEffect(() => { - if (initialQuery) { - setQuery(initialQuery); - } - }, [initialQuery]); - - useEffect(() => { - setQuery((prev) => ({ - ...prev, - context: context.reduce((acc, e) => acc + e + "\n", ""), - context_json: contextJSON, - })); - }, [context]); - return ( -
    - {context.length > 0 && ( -
    -
    -

    - {expanded ? "Hide Context" : "Show Context"} -

    - setExpanded((prev) => !prev)} - > -
    - -
    -
    -
    - {expanded && ( -
    -
    - -
    - {/* {query.context !== "" && ( - { - setTranslating(true); - console.log(query.context); - const res = await gptApi.translate( - query.context - ); - if (res.success) { - console.log( - "Context translated successfully" - ); - setQuery((prev) => ({ - ...prev, - context: res.data, - })); - } else { - console.error( - "Error translating context" - ); - } - setTranslating(false); - }} - loading={translating} - className="flex flex-row gap-2 items-center" - > - Translate - - )} */} - - {/* */} -
    -
    - {query.context !== "" && ( -
    - - setQuery((prev) => ({ - ...prev, - context: e.target.value, - })) - } - // sx={{ - // borderColor: "black", - // borderWidth: "1px", - // borderRadius: "3px", - // // padding: "2px 5px", - // }} - className="p-3 w-full !bg-slate-100" - > -

    - {query.context - .split("\n") - .map((line, index) => ( - - {/* {line} */} -

    - {/*
    */} - - ))} -

    -
    - {/*