diff --git a/client/public/images/skyGarden/skyGardenIndoor.jpg b/client/public/images/skyGarden/skyGardenIndoor.jpg new file mode 100644 index 0000000..2bd69ff Binary files /dev/null and b/client/public/images/skyGarden/skyGardenIndoor.jpg differ diff --git a/client/public/images/skyGarden/skyGardenOutdoor.jpg b/client/public/images/skyGarden/skyGardenOutdoor.jpg new file mode 100644 index 0000000..b53109c Binary files /dev/null and b/client/public/images/skyGarden/skyGardenOutdoor.jpg differ diff --git a/client/public/images/skyGardenSlider/1.jpg b/client/public/images/skyGardenSlider/1.jpg new file mode 100644 index 0000000..b364187 Binary files /dev/null and b/client/public/images/skyGardenSlider/1.jpg differ diff --git a/client/public/images/skyGardenSlider/2.jpg b/client/public/images/skyGardenSlider/2.jpg new file mode 100644 index 0000000..3a48479 Binary files /dev/null and b/client/public/images/skyGardenSlider/2.jpg differ diff --git a/client/public/images/skyGardenSlider/3.jpg b/client/public/images/skyGardenSlider/3.jpg new file mode 100644 index 0000000..d4e11a8 Binary files /dev/null and b/client/public/images/skyGardenSlider/3.jpg differ diff --git a/client/public/images/skyGardenSlider/4.jpg b/client/public/images/skyGardenSlider/4.jpg new file mode 100644 index 0000000..255e023 Binary files /dev/null and b/client/public/images/skyGardenSlider/4.jpg differ diff --git a/client/src/components/Checkbox2.tsx b/client/src/components/Checkbox2.tsx new file mode 100644 index 0000000..249a464 --- /dev/null +++ b/client/src/components/Checkbox2.tsx @@ -0,0 +1,35 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { useState } from "react"; +import CheckIcon from "./icons/CheckIcon"; + +interface Props { + filterName?: string; + defaultIsChecked?: boolean; + onChange: (isChecked: boolean, filterName: string) => void; +} + +function Checkbox2({ filterName, defaultIsChecked, onChange }: Props) { + const [isChecked, setIsChecked] = useState( + defaultIsChecked || false + ); + + function handleClick() { + setIsChecked((prev) => { + onChange(!prev, filterName || ""); + return !prev; + }); + } + + return ( +
+ {isChecked && } +
+ ); +} + +export default Checkbox2; diff --git a/client/src/components/complexWingPage/SequenceWing/MobileSkygardenDescription.tsx b/client/src/components/complexWingPage/SequenceWing/MobileSkygardenDescription.tsx index 77fd6a6..ad5ca5a 100644 --- a/client/src/components/complexWingPage/SequenceWing/MobileSkygardenDescription.tsx +++ b/client/src/components/complexWingPage/SequenceWing/MobileSkygardenDescription.tsx @@ -35,7 +35,7 @@ const MobileSkygardenDescription = ({

Indoor

-

3 amenties

+

3 amenities

@@ -46,7 +46,7 @@ const MobileSkygardenDescription = ({

Studio

-

14 amenties

+

14 amenities

); diff --git a/client/src/consts/initialMasterplanFilters.ts b/client/src/consts/initialMasterplanFilters.ts index 0a88901..c3bd535 100644 --- a/client/src/consts/initialMasterplanFilters.ts +++ b/client/src/consts/initialMasterplanFilters.ts @@ -53,7 +53,7 @@ const initialAparmentTypeCheckboxes: ICheckbox[] = [ const initialViewCheckboxes: ICheckbox[] = [ { title: "Burj Khalifa", id: "1", selected: false, value: "BK" }, - { title: "Amenties", id: "2", selected: false, value: "Amenities" }, + { title: "Amenities", id: "2", selected: false, value: "Amenities" }, { title: "Downtown", id: "3", selected: false, value: "DT" }, { title: "Canal", id: "4", selected: false, value: "Canal" }, { title: "Business Bay", id: "5", selected: false, value: "Business Bay" }, diff --git a/client/src/index.css b/client/src/index.css index 7f2fcbd..6b790f1 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -35,8 +35,9 @@ } body { + /* font-family: "Usual"; */ background-color: #f3f3f2; - color: #091118; + color: #0d1922b2; } .font-usual { diff --git a/client/src/main.tsx b/client/src/main.tsx index cf0660f..3829f99 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -9,10 +9,11 @@ import AboutProjectsPage from "./pages/AboutProjectsPage"; import UnitTypesPage from "./pages/UnitTypesPage"; import AboutPage from "./pages/AboutPage"; import FavoritesPage from "./pages/FavoritesPage"; -import SearchPage from "./pages/SearchPage"; +// import SearchPage from "./pages/SearchPage"; import ApartmentPage from "./pages/ApartmentPage"; import VirtualTour from "./pages/VirtualTour"; import UnitTypesItemPage from "./pages/UnitTypesItemPage"; +import SearchPage2 from "./pages/SearchPage2"; const router = createBrowserRouter([ { @@ -62,7 +63,7 @@ const router = createBrowserRouter([ }, { path: "search", - element: , + element: , }, { path: "search/:id", diff --git a/client/src/pages/SearchPage2.tsx b/client/src/pages/SearchPage2.tsx new file mode 100644 index 0000000..a8a5b23 --- /dev/null +++ b/client/src/pages/SearchPage2.tsx @@ -0,0 +1,363 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { useEffect, useState } from "react"; +import RestartIcon from "../components/icons/RestartIcon"; +import api from "../utils/api"; +import IUnit from "../types/IUnit"; +import Checkbox2 from "../components/Checkbox2"; +import HeartIcon from "../components/icons/HeartIcon"; + +function SearchPage2() { + const [units, setUnits] = useState([]); + const [filteredUnits, setFilteredUnits] = useState([]); + const [unitTypeFilters, setUnitTypeFilters] = useState([]); + + async function getUnits() { + try { + const result: IUnit[] = await api.get("units").json(); + + setUnits(result); + } catch (error) { + // + } + } + + function getImageSrc(unitNo: string): string { + const side = unitNo.split("-")[0]; + const floor = Number(unitNo.split("-")[1].slice(0, -2)); + const unitNumber = Number(unitNo.split("-")[1].slice(-2)); + + if (side === "W") { + // Side "W" + if (floor < 24) { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/studio_flex_left.png"; + case 10: + return "/images/layouts/studio_flex_left.png"; + case 11: + return "/images/layouts/studio_flex_left.png"; + case 12: + return "/images/layouts/studio_flex_left.png"; + case 13: + return "/images/layouts/studio_flex_left.png"; + case 14: + return "/images/layouts/studio_flex_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + case 17: + return "/images/layouts/2br_b_left.png"; + } + } else { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/1br_d_left.png"; + case 10: + return "/images/layouts/studio_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/1br_d_left.png"; + case 13: + return "/images/layouts/1br_c_left.png"; + case 14: + return "/images/layouts/1br_c_left.png"; + case 15: + return "/images/layouts/2br_b_left.png"; + } + } + } else { + // Side "E" + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_c_left.png"; + case 7: + return "/images/layouts/1br_c_left.png"; + case 8: + return "/images/layouts/1br_b_left.png"; + case 9: + return "/images/layouts/1br_b_left.png"; + case 10: + return "/images/layouts/1br_c_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/studio_left.png"; + case 13: + return "/images/layouts/studio_left.png"; + case 14: + return "/images/layouts/studio_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + } + } + + console.log(side, floor, unitNumber); + + // switch (unitType) { + // case "Studio Squared": + // return "/images/layouts/studio_left.png"; + // case "Studio Flex": + // return "/images/layouts/studio_flex_left.png"; + // case "1 BR Squared": + // return "/images/layouts/1br_a_left.png"; + // case "2 BR Squared": + // return "/images/layouts/2br_a_left.png"; + // default: + // return ""; + // } + + return ""; + } + + useEffect(() => { + if (unitTypeFilters.length) { + setFilteredUnits( + units.filter((unit) => unitTypeFilters.includes(unit.unitType)) + ); + } else { + setFilteredUnits([]); + } + }, [unitTypeFilters]); + + useEffect(() => { + if (!filteredUnits.length) return; + + console.log("filteredUnits", filteredUnits); + }, [filteredUnits]); + + useEffect(() => { + getUnits(); + }); + + return ( +
+
+
+

Filters

+
+ +
+
+ {/*
*/} +
+

Apartment type

+
+
+
+ { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

Studio Flex

+
+
+

+ { + units.filter((unit) => unit.unitType === "Studio Flex") + .length + } +

+
+
+
+
+ { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

Studio²

+
+
+

+ { + units.filter((unit) => unit.unitType === "Studio Squared") + .length + } +

+
+
+
+
+ { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

1 Bedroom²

+
+
+

+ { + units.filter((unit) => unit.unitType === "1 BR Squared") + .length + } +

+
+
+
+
+ { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

2 Bedroom²

+
+
+

+ { + units.filter((unit) => unit.unitType === "2 BR Squared") + .length + } +

+
+
+
+
+
+
+
+
+
+
+
+

+ Units{" "} + {filteredUnits.length || units.length} +

+
+
+ +
+
+
+ {(filteredUnits.length ? filteredUnits : units).map((unit) => ( +
+
+
+

{unit.projectName}

+
+

+ {unit.unitNo[0] === "E" ? "East" : "West"} Wing +

+
+

{unit.floor}

+
+

{unit.unitNo}

+
+
+ +
+
+ +
+
+

+ {unit.unitType}, {unit.totalArea} Sqft +

+

+ {(unit.unitPrice && + `AED ${unit.unitPrice.toLocaleString()}`) || + "Unavailable"} +

+
+
+ ))} +
+
+
+
+ ); +} + +export default SearchPage2; diff --git a/client/src/pages/UnitTypesItemPage.tsx b/client/src/pages/UnitTypesItemPage.tsx index 80fbb3d..5fb02eb 100644 --- a/client/src/pages/UnitTypesItemPage.tsx +++ b/client/src/pages/UnitTypesItemPage.tsx @@ -31,7 +31,7 @@ function UnitTypesItemPage() {
{unitType?.legends.map((legend, index) => (
-
+
{index + 1}

{legend}

diff --git a/client/src/types/IUnit.ts b/client/src/types/IUnit.ts new file mode 100644 index 0000000..c486511 --- /dev/null +++ b/client/src/types/IUnit.ts @@ -0,0 +1,19 @@ +interface IUnit { + propertyName: string; + projectName: string; + floor: number; + unitNo: string; + propertyStatus: string; + unitType: string; + unitView: string; + furnished: string; + totalArea: number; + suiteArea: number; + balconyArea: number; + bedrooms: number; + bathrooms: number; + parkingSpaces: number; + unitPrice?: number; +} + +export default IUnit; diff --git a/client/src/utils/api.ts b/client/src/utils/api.ts new file mode 100644 index 0000000..1a868e6 --- /dev/null +++ b/client/src/utils/api.ts @@ -0,0 +1,7 @@ +import ky from "ky"; + +const api = ky.extend({ + prefixUrl: import.meta.env.VITE_SERVER_API, +}); + +export default api; diff --git a/server/.env b/server/.env index 9956197..1f63a19 100644 --- a/server/.env +++ b/server/.env @@ -1,2 +1,3 @@ PORT=4002 -REFRESH_TOKEN=1000.ca08e1e4dc5fe081e2bd7fdbd0adf5e6.68b8da640d7322a889f10eddbcf5ee6b \ No newline at end of file +REFRESH_TOKEN=1000.ca08e1e4dc5fe081e2bd7fdbd0adf5e6.68b8da640d7322a889f10eddbcf5ee6b +MONGO_URI=mongodb://root:p62Z!ZatgY25@194.26.138.94:27017 \ No newline at end of file diff --git a/server/package.json b/server/package.json index 17e8ac4..26f5db3 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "name": "client", + "name": "server", "private": true, "version": "0.0.0", "type": "module", @@ -12,6 +12,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "mongoose": "^8.5.1", "morgan": "^1.10.0", "winston": "^3.13.0" }, diff --git a/server/src/config/db.ts b/server/src/config/db.ts new file mode 100644 index 0000000..563561b --- /dev/null +++ b/server/src/config/db.ts @@ -0,0 +1,16 @@ +import { connect } from "mongoose"; + +async function connectDB() { + try { + await connect(process.env.MONGO_URI!, { dbName: "irth" }); + console.log("MongoDB connected..."); + } catch (error) { + if (error instanceof Error) { + console.error(error.message); + } + + process.exit(1); + } +} + +export default connectDB; \ No newline at end of file diff --git a/server/src/data/irth_unit_pirces.json b/server/src/data/irth_unit_pirces.json new file mode 100644 index 0000000..ad1f50a --- /dev/null +++ b/server/src/data/irth_unit_pirces.json @@ -0,0 +1,302 @@ +[ + { + "unitName": "RHMD-8E-06", + "bedrooms": "1 BR Squared", + "floor": 8, + "position": "Front", + "suiteArea": 487, + "balconyArea": 121, + "unitArea": 608, + "unitPrice": 1699888 + }, + { + "unitName": "RHMD-9E-01", + "bedrooms": "2 BR Squared", + "floor": 9, + "position": "Front", + "suiteArea": 737, + "balconyArea": 177, + "unitArea": 914, + "unitPrice": 2430888 + }, + { + "unitName": "RHMD-9W-06", + "bedrooms": "1 BR Squared", + "floor": 9, + "position": "Front", + "suiteArea": 496, + "balconyArea": 121, + "unitArea": 618, + "unitPrice": 1732888 + }, + { + "unitName": "RHMD-9W-15", + "bedrooms": "1 BR Squared", + "floor": 9, + "position": "Back", + "suiteArea": 520, + "balconyArea": 122, + "unitArea": 642, + "unitPrice": 1594888 + }, + { + "unitName": "RHMD-9W-17", + "bedrooms": "2 BR Squared", + "floor": 9, + "position": "Back", + "suiteArea": 729, + "balconyArea": 328, + "unitArea": " 1 058 ", + "unitPrice": 2364888 + }, + { + "unitName": "RHMD-11E-14", + "bedrooms": "Studio Squared", + "floor": 11, + "position": "Back", + "suiteArea": 339, + "balconyArea": 78, + "unitArea": 416, + "unitPrice": 1175888 + }, + { + "unitName": "RHMD-11W-12", + "bedrooms": "Studio Flex", + "floor": 11, + "position": "Back", + "suiteArea": 284, + "balconyArea": 72, + "unitArea": 356, + "unitPrice": 1054888 + }, + { + "unitName": "RHMD-12W-01", + "bedrooms": "2 BR Squared", + "floor": 12, + "position": "Front", + "suiteArea": 737, + "balconyArea": 177, + "unitArea": 914, + "unitPrice": 2454888 + }, + { + "unitName": "RHMD-12W-07", + "bedrooms": "1 BR Squared", + "floor": 12, + "position": "Front", + "suiteArea": 492, + "balconyArea": 129, + "unitArea": 622, + "unitPrice": 1784888 + }, + { + "unitName": "RHMD-12W-13", + "bedrooms": "Studio Flex", + "floor": 12, + "position": "Back", + "suiteArea": 273, + "balconyArea": 68, + "unitArea": 341, + "unitPrice": 1014888 + }, + { + "unitName": "RHMD-12W-17", + "bedrooms": "2 BR Squared", + "floor": 12, + "position": "Back", + "suiteArea": 729, + "balconyArea": 328, + "unitArea": " 1 058 ", + "unitPrice": 2388888 + }, + { + "unitName": "RHMD-15W-04", + "bedrooms": "Studio Squared", + "floor": 15, + "position": "Front", + "suiteArea": 320, + "balconyArea": 81, + "unitArea": 401, + "unitPrice": 1294888 + }, + { + "unitName": "RHMD-15W-16", + "bedrooms": "1 BR Squared", + "floor": 15, + "position": "Back", + "suiteArea": 487, + "balconyArea": 122, + "unitArea": 609, + "unitPrice": 1544888 + }, + { + "unitName": "RHMD-20E-02", + "bedrooms": "Studio Squared", + "floor": 20, + "position": "Front", + "suiteArea": 325, + "balconyArea": 78, + "unitArea": 403, + "unitPrice": 1339888 + }, + { + "unitName": "RHMD-21W-04", + "bedrooms": "Studio Squared", + "floor": 21, + "position": "Front", + "suiteArea": 320, + "balconyArea": 81, + "unitArea": 401, + "unitPrice": 1340888 + }, + { + "unitName": "RHMD-21W-10", + "bedrooms": "Studio Flex", + "floor": 21, + "position": "Back", + "suiteArea": 273, + "balconyArea": 68, + "unitArea": 341, + "unitPrice": 1052888 + }, + { + "unitName": "RHMD-24E-04", + "bedrooms": "Studio Squared", + "floor": 24, + "position": "Front", + "suiteArea": 320, + "balconyArea": 81, + "unitArea": 401, + "unitPrice": 1366888 + }, + { + "unitName": "RHMD-24W-10", + "bedrooms": "Studio Squared", + "floor": 24, + "position": "Back", + "suiteArea": 320, + "balconyArea": 81, + "unitArea": 401, + "unitPrice": 1202888 + }, + { + "unitName": "RHMD-24W-12", + "bedrooms": "1 BR Squared", + "floor": 24, + "position": "Back", + "suiteArea": 501, + "balconyArea": 119, + "unitArea": 619, + "unitPrice": 1605888 + }, + { + "unitName": "RHMD-25E-15", + "bedrooms": "1 BR Squared", + "floor": 25, + "position": "Back", + "suiteArea": 520, + "balconyArea": 122, + "unitArea": 642, + "unitPrice": 1674888 + }, + { + "unitName": "RHMD-26E-12", + "bedrooms": "Studio Squared", + "floor": 26, + "position": "Back", + "suiteArea": 319, + "balconyArea": 81, + "unitArea": 400, + "unitPrice": 1216888 + }, + { + "unitName": "RHMD-26E-14", + "bedrooms": "Studio Squared", + "floor": 26, + "position": "Back", + "suiteArea": 339, + "balconyArea": 78, + "unitArea": 416, + "unitPrice": 1264888 + }, + { + "unitName": "RHMD-26W-09", + "bedrooms": "1 BR Squared", + "floor": 26, + "position": "Back", + "suiteArea": 500, + "balconyArea": 118, + "unitArea": 618, + "unitPrice": 1624888 + }, + { + "unitName": "RHMD-26W-14", + "bedrooms": "1 BR Squared", + "floor": 26, + "position": "Back", + "suiteArea": 487, + "balconyArea": 122, + "unitArea": 609, + "unitPrice": 1635888 + }, + { + "unitName": "RHMD-27E-12", + "bedrooms": "Studio Squared", + "floor": 27, + "position": "Back", + "suiteArea": 319, + "balconyArea": 81, + "unitArea": 400, + "unitPrice": 1224888 + }, + { + "unitName": "RHMD-27E-13", + "bedrooms": "Studio Squared", + "floor": 27, + "position": "Back", + "suiteArea": 309, + "balconyArea": 78, + "unitArea": 386, + "unitPrice": 1181888 + }, + { + "unitName": "RHMD-28E-05", + "bedrooms": "Studio Squared", + "floor": 28, + "position": "Front", + "suiteArea": 319, + "balconyArea": 81, + "unitArea": 400, + "unitPrice": 1397888 + }, + { + "unitName": "RHMD-29W-13", + "bedrooms": "1 BR Squared", + "floor": 29, + "position": "Back", + "suiteArea": 520, + "balconyArea": 122, + "unitArea": 642, + "unitPrice": 1756888 + }, + { + "unitName": "RHMD-30W-11", + "bedrooms": "Studio Squared", + "floor": 30, + "position": "Back", + "suiteArea": 320, + "balconyArea": 81, + "unitArea": 401, + "unitPrice": 1248888 + }, + { + "unitName": "RHMD-30W-15", + "bedrooms": "2 BR Squared", + "floor": 30, + "position": "Back", + "suiteArea": 729, + "balconyArea": 328, + "unitArea": " 1 058 ", + "unitPrice": 2730888 + } +] \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index c820e83..a347f97 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -4,29 +4,31 @@ import cors from "cors"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; +import connectDB from "./config/db.js"; import morgan from "morgan"; -import apartmentsRoute from "./routes/apartments.js"; -import apartmentRoute from "./routes/apartment.js"; -import updateAccessToken from "./routes/zohoAccessToken.js"; +import unitsRoute from "./routes/unitsRoute.js"; +// import updateApartmentsRoute from "./routes/updateApartmentsRoute.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const app = express(); -const port = process.env.PORT || 3000; - +!fs.existsSync("logs") && fs.mkdirSync("logs"); const accessLogStream = fs.createWriteStream( path.join(__dirname, "../logs/access.log"), { flags: "a" } ); +await connectDB(); + +const app = express(); +const port = process.env.PORT || 3000; + app.use(cors()); app.use(json()); app.use(morgan("combined", { stream: accessLogStream })); -app.use("/apartments", apartmentsRoute); -app.use("/apartment", apartmentRoute); -app.use("/updateAccessToken", updateAccessToken); +app.use("/units", unitsRoute); +// app.use("/update-apartments", updateApartmentsRoute); app.listen(port, () => { console.log(`Server is listening on port ${port}`); diff --git a/server/src/models/Unit.ts b/server/src/models/Unit.ts new file mode 100644 index 0000000..e918735 --- /dev/null +++ b/server/src/models/Unit.ts @@ -0,0 +1,60 @@ +import { model, Schema } from "mongoose"; + +const unitSchema = new Schema( + { + propertyName: { + type: String, + }, + projectName: { + type: String, + }, + floor: { + type: Number, + }, + unitNo: { + type: String, + }, + propertyStatus: { + type: String, + }, + unitType: { + type: String, + }, + unitView: { + type: String, + }, + furnished: { + type: String, + }, + totalArea: { + type: Number, + }, + suiteArea: { + type: Number, + }, + balconyArea: { + type: Number, + }, + bedrooms: { + type: Number, + }, + bathrooms: { + type: Number, + }, + parkingSpaces: { + type: Number, + }, + unitPrice: { + type: Number, + }, + }, + { + timestamps: true, + toJSON: { virtuals: true }, + toObject: { virtuals: true }, + } +); + +const Unit = model("Unit", unitSchema); + +export default Unit; diff --git a/server/src/routes/unitsRoute.ts b/server/src/routes/unitsRoute.ts new file mode 100644 index 0000000..2235175 --- /dev/null +++ b/server/src/routes/unitsRoute.ts @@ -0,0 +1,28 @@ +import { Router } from "express"; +import Unit from "../models/Unit.js"; + +const router = Router(); + +router.get("/", async (req, res) => { + try { + const units = await Unit.find(); + + res.json(units); + } catch (error) { + res.json({ error: (error as Error).message }); + } +}); + +router.get("/:id", async (req, res) => { + try { + const unit = await Unit.findById(req.params.id); + + res.json(unit); + } catch (error) { + res.json({ error: (error as Error).message }); + } +}); + +const apartmentRoute = router; + +export default apartmentRoute; diff --git a/server/src/routes/updateApartmentsRoute.ts b/server/src/routes/updateApartmentsRoute.ts new file mode 100644 index 0000000..8ff0cf9 --- /dev/null +++ b/server/src/routes/updateApartmentsRoute.ts @@ -0,0 +1,30 @@ +import { Router } from "express"; +import data from "../data/irth_unit_pirces.json" assert { type: "json" }; +import Unit from "../models/Unit.js"; + +const router = Router(); + +router.get("/", async (req, res) => { + for (const item of data) { + const result = await Unit.findOneAndUpdate( + { propertyName: item.unitName }, + { unitPrice: item.unitPrice }, + { new: true } + ); + + console.log("result", result); + } + + // const file = fs.readFileSync( + // path.resolve("./src/data/irth_unit_pirces.json"), + // { encoding: "utf8" } + // ); + + // const data = JSON.parse(file); + + res.json({ ok: 1 }); +}); + +const updateApartmentsRoute = router; + +export default updateApartmentsRoute; diff --git a/server/tsconfig.json b/server/tsconfig.json index 56b788b..c5b1bb5 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -39,7 +39,7 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true /* Enable importing .json files. */, // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ diff --git a/server/yarn.lock b/server/yarn.lock index e984e1a..12cd526 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -41,6 +41,13 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@mongodb-js/saslprep@^1.1.5": + version "1.1.8" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz#d39744540be8800d17749990b0da95b4271840d1" + integrity sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ== + dependencies: + sparse-bitfield "^3.0.3" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -159,6 +166,18 @@ resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== +"@types/webidl-conversions@*": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" + integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== + +"@types/whatwg-url@^11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.5.tgz#aaa2546e60f0c99209ca13360c32c78caf2c409f" + integrity sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ== + dependencies: + "@types/webidl-conversions" "*" + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -252,6 +271,11 @@ braces@~3.0.2: dependencies: fill-range "^7.1.1" +bson@^6.7.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.8.0.tgz#5063c41ba2437c2b8ff851b50d9e36cb7aaa7525" + integrity sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ== + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -371,7 +395,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@^4: +debug@4.x, debug@^4: version "4.3.5" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== @@ -652,6 +676,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +kareem@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.6.3.tgz#23168ec8ffb6c1abfd31b7169a6fb1dd285992ac" + integrity sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q== + kuler@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" @@ -679,6 +708,11 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +memory-pager@^1.0.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" + integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -713,6 +747,36 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +mongodb-connection-string-url@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz#c13e6ac284ae401752ebafdb8cd7f16c6723b141" + integrity sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg== + dependencies: + "@types/whatwg-url" "^11.0.2" + whatwg-url "^13.0.0" + +mongodb@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.7.0.tgz#f86e51e6530e6a2ca4a99d7cfdf6f409223ac199" + integrity sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA== + dependencies: + "@mongodb-js/saslprep" "^1.1.5" + bson "^6.7.0" + mongodb-connection-string-url "^3.0.0" + +mongoose@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.5.1.tgz#011192edf77af54dd0826a836459212da317c503" + integrity sha512-OhVcwVl91A1G6+XpjDcpkGP7l7ikZkxa0DylX7NT/lcEqAjggzSdqDxb48A+xsDxqNAr0ntSJ1yiE3+KJTOd5Q== + dependencies: + bson "^6.7.0" + kareem "2.6.3" + mongodb "6.7.0" + mpath "0.9.0" + mquery "5.0.0" + ms "2.1.3" + sift "17.1.3" + morgan@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" @@ -724,6 +788,18 @@ morgan@^1.10.0: on-finished "~2.3.0" on-headers "~1.0.2" +mpath@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.9.0.tgz#0c122fe107846e31fc58c75b09c35514b3871904" + integrity sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew== + +mquery@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-5.0.0.tgz#a95be5dfc610b23862df34a47d3e5d60e110695d" + integrity sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg== + dependencies: + debug "4.x" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -829,6 +905,11 @@ pstree.remy@^1.1.8: resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +punycode@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -948,6 +1029,11 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +sift@17.1.3: + version "17.1.3" + resolved "https://registry.yarnpkg.com/sift/-/sift-17.1.3.tgz#9d2000d4d41586880b0079b5183d839c7a142bf7" + integrity sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ== + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -962,6 +1048,13 @@ simple-update-notifier@^2.0.0: dependencies: semver "^7.5.3" +sparse-bitfield@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" + integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== + dependencies: + memory-pager "^1.0.2" + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -1008,6 +1101,13 @@ touch@^3.1.0: resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + triple-beam@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" @@ -1080,6 +1180,19 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-url@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-13.0.0.tgz#b7b536aca48306394a34e44bda8e99f332410f8f" + integrity sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig== + dependencies: + tr46 "^4.1.1" + webidl-conversions "^7.0.0" + winston-transport@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0"