From d8c8482696c52ca40c709e380a92e0a7354d2790 Mon Sep 17 00:00:00 2001
From: Piotr K <44520613+astropio3000@users.noreply.github.com>
Date: Sat, 27 May 2023 00:16:50 +0200
Subject: [PATCH] cokolwiek
---
apps/frontend/package-lock.json | 256 +++++++++-
apps/frontend/package.json | 6 +-
apps/frontend/src/app/app-routing.module.ts | 12 +-
apps/frontend/src/app/app.component.html | 483 ------------------
apps/frontend/src/app/app.module.ts | 24 +-
apps/frontend/src/app/models/issue.mock.ts | 0
apps/frontend/src/app/models/issue.model.ts | 10 +
.../app/modules/issue/issue-routing.module.ts | 11 +
.../app/modules/issue/issue.component.html | 9 +
.../app/modules/issue/issue.component.scss | 0
.../app/modules/issue/issue.component.spec.ts | 21 +
.../src/app/modules/issue/issue.component.ts | 23 +
.../src/app/modules/issue/issue.module.ts | 11 +
.../issue-element.component.html | 3 +
.../issue-element.component.scss | 0
.../issue-element.component.spec.ts | 21 +
.../issue-element/issue-element.component.ts | 11 +
.../app/modules/issues/issue.component.html | 6 +
.../app/modules/issues/issue.component.scss | 0
.../modules/issues/issue.component.spec.ts | 21 +
.../src/app/modules/issues/issue.component.ts | 21 +
.../src/app/modules/issues/issue.module.ts | 13 +
.../src/app/modules/map/map-routing.module.ts | 11 +
.../src/app/modules/map/map.component.html | 4 +
.../src/app/modules/map/map.component.scss | 9 +
.../src/app/modules/map/map.component.spec.ts | 21 +
.../src/app/modules/map/map.component.ts | 63 +++
.../src/app/modules/map/map.module.ts | 13 +
.../modules/map/services/points.service.ts | 6 +
.../src/app/services/issues.service.ts | 39 ++
.../src/app/store/actions/issue.actions.ts | 13 +
.../src/app/store/effect/issue.effect.ts | 25 +
.../src/app/store/reducer/issue.reducer.ts | 45 ++
.../app/store/selectors/issue.selectors.ts | 9 +
.../src/app/store/state/issue.state.ts | 5 +
apps/frontend/src/index.html | 28 +-
36 files changed, 745 insertions(+), 508 deletions(-)
create mode 100644 apps/frontend/src/app/models/issue.mock.ts
create mode 100644 apps/frontend/src/app/models/issue.model.ts
create mode 100644 apps/frontend/src/app/modules/issue/issue-routing.module.ts
create mode 100644 apps/frontend/src/app/modules/issue/issue.component.html
create mode 100644 apps/frontend/src/app/modules/issue/issue.component.scss
create mode 100644 apps/frontend/src/app/modules/issue/issue.component.spec.ts
create mode 100644 apps/frontend/src/app/modules/issue/issue.component.ts
create mode 100644 apps/frontend/src/app/modules/issue/issue.module.ts
create mode 100644 apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.html
create mode 100644 apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.scss
create mode 100644 apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.spec.ts
create mode 100644 apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.ts
create mode 100644 apps/frontend/src/app/modules/issues/issue.component.html
create mode 100644 apps/frontend/src/app/modules/issues/issue.component.scss
create mode 100644 apps/frontend/src/app/modules/issues/issue.component.spec.ts
create mode 100644 apps/frontend/src/app/modules/issues/issue.component.ts
create mode 100644 apps/frontend/src/app/modules/issues/issue.module.ts
create mode 100644 apps/frontend/src/app/modules/map/map-routing.module.ts
create mode 100644 apps/frontend/src/app/modules/map/map.component.html
create mode 100644 apps/frontend/src/app/modules/map/map.component.scss
create mode 100644 apps/frontend/src/app/modules/map/map.component.spec.ts
create mode 100644 apps/frontend/src/app/modules/map/map.component.ts
create mode 100644 apps/frontend/src/app/modules/map/map.module.ts
create mode 100644 apps/frontend/src/app/modules/map/services/points.service.ts
create mode 100644 apps/frontend/src/app/services/issues.service.ts
create mode 100644 apps/frontend/src/app/store/actions/issue.actions.ts
create mode 100644 apps/frontend/src/app/store/effect/issue.effect.ts
create mode 100644 apps/frontend/src/app/store/reducer/issue.reducer.ts
create mode 100644 apps/frontend/src/app/store/selectors/issue.selectors.ts
create mode 100644 apps/frontend/src/app/store/state/issue.state.ts
diff --git a/apps/frontend/package-lock.json b/apps/frontend/package-lock.json
index cc7c615..071dbef 100644
--- a/apps/frontend/package-lock.json
+++ b/apps/frontend/package-lock.json
@@ -19,6 +19,10 @@
"@fortawesome/angular-fontawesome": "^0.13.0",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
+ "@ngrx/effects": "^16.0.0",
+ "@ngrx/store": "^16.0.0",
+ "@ngrx/store-devtools": "^16.0.0",
+ "ol": "^7.3.0",
"primeng": "^16.0.0-rc.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@@ -2876,6 +2880,82 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
+ "node_modules/@mapbox/jsonlint-lines-primitives": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
+ "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@mapbox/mapbox-gl-style-spec": {
+ "version": "13.28.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.28.0.tgz",
+ "integrity": "sha512-B8xM7Fp1nh5kejfIl4SWeY0gtIeewbuRencqO3cJDrCHZpaPg7uY+V8abuR+esMeuOjRl5cLhVTP40v+1ywxbg==",
+ "dependencies": {
+ "@mapbox/jsonlint-lines-primitives": "~2.0.2",
+ "@mapbox/point-geometry": "^0.1.0",
+ "@mapbox/unitbezier": "^0.0.0",
+ "csscolorparser": "~1.0.2",
+ "json-stringify-pretty-compact": "^2.0.0",
+ "minimist": "^1.2.6",
+ "rw": "^1.3.3",
+ "sort-object": "^0.3.2"
+ },
+ "bin": {
+ "gl-style-composite": "bin/gl-style-composite.js",
+ "gl-style-format": "bin/gl-style-format.js",
+ "gl-style-migrate": "bin/gl-style-migrate.js",
+ "gl-style-validate": "bin/gl-style-validate.js"
+ }
+ },
+ "node_modules/@mapbox/point-geometry": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
+ "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
+ },
+ "node_modules/@mapbox/unitbezier": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz",
+ "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA=="
+ },
+ "node_modules/@ngrx/effects": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-16.0.0.tgz",
+ "integrity": "sha512-l3H/yCwVl8DPmUasOEDthdv9lZMhCSJwBxfSXjUW7gKJVEamP3PSuvExp0ZpW9RULPblgcfTM1TH8VcPAHelQw==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@angular/core": "^16.0.0",
+ "@ngrx/store": "16.0.0",
+ "rxjs": "^6.5.3 || ^7.5.0"
+ }
+ },
+ "node_modules/@ngrx/store": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-16.0.0.tgz",
+ "integrity": "sha512-bmr0KLITh9u1DJO51USTc4OAKX+su06efhTdNiQV/wagifpbC4kA8zr2hdstKMNG3Z5EKTX3XLFanIiREkd6JQ==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@angular/core": "^16.0.0",
+ "rxjs": "^6.5.3 || ^7.5.0"
+ }
+ },
+ "node_modules/@ngrx/store-devtools": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-16.0.0.tgz",
+ "integrity": "sha512-20+jv+k6W3PM6gohiYaUXiEv9U0fFLMZJb7c7ARRsu1vWICC59dW77OPMhoVrqDLoMgr4gMikw/BwfceSLxCJA==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@ngrx/store": "16.0.0",
+ "rxjs": "^6.5.3 || ^7.5.0"
+ }
+ },
"node_modules/@ngtools/webpack": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.0.3.tgz",
@@ -3091,6 +3171,11 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/@petamoriken/float16": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.1.tgz",
+ "integrity": "sha512-oj3dU9kuMy8AqrreIboVh3KCJGSQO5T+dJ8JQFl369961jTWvPLP1GIlLy0FVoWehXLoI9BXygu/yzuNiIHBlg=="
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -4965,6 +5050,11 @@
"url": "https://github.com/sponsors/fb55"
}
},
+ "node_modules/csscolorparser": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
+ "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -5186,6 +5276,11 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
+ "node_modules/earcut": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
+ "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
+ },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -6023,6 +6118,28 @@
"node": ">=6.9.0"
}
},
+ "node_modules/geotiff": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.0.7.tgz",
+ "integrity": "sha512-FKvFTNowMU5K6lHYY2f83d4lS2rsCNdpUC28AX61x9ZzzqPNaWFElWv93xj0eJFaNyOYA63ic5OzJ88dHpoA5Q==",
+ "dependencies": {
+ "@petamoriken/float16": "^3.4.7",
+ "lerc": "^3.0.0",
+ "pako": "^2.0.4",
+ "parse-headers": "^2.0.2",
+ "quick-lru": "^6.1.1",
+ "web-worker": "^1.2.0",
+ "xml-utils": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=10.19"
+ }
+ },
+ "node_modules/geotiff/node_modules/pako": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
+ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
+ },
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -6442,7 +6559,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -7106,6 +7222,11 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
+ "node_modules/json-stringify-pretty-compact": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz",
+ "integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ=="
+ },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -7392,6 +7513,11 @@
"shell-quote": "^1.7.3"
}
},
+ "node_modules/lerc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz",
+ "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww=="
+ },
"node_modules/less": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz",
@@ -7860,6 +7986,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "node_modules/mapbox-to-css-font": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.2.tgz",
+ "integrity": "sha512-f+NBjJJY4T3dHtlEz1wCG7YFlkODEjFIYlxDdLIDMNpkSksqTt+l/d4rjuwItxuzkuMFvPyrjzV2lxRM4ePcIA=="
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -8007,7 +8138,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -8741,6 +8871,31 @@
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
"dev": true
},
+ "node_modules/ol": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/ol/-/ol-7.3.0.tgz",
+ "integrity": "sha512-08vJE4xITKPazQ9qJjeqYjRngnM9s+1eSv219Pdlrjj3LpLqjEH386ncq+76Dw1oGPGR8eLVEePk7FEd9XqqMw==",
+ "dependencies": {
+ "earcut": "^2.2.3",
+ "geotiff": "^2.0.7",
+ "ol-mapbox-style": "^9.2.0",
+ "pbf": "3.2.1",
+ "rbush": "^3.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/openlayers"
+ }
+ },
+ "node_modules/ol-mapbox-style": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-9.7.0.tgz",
+ "integrity": "sha512-YX3u8FBJHsRHaoGxmd724Mp5WPTuV7wLQW6zZhcihMuInsSdCX1EiZfU+8IAL7jG0pbgl5YgC0aWE/MXJcUXxg==",
+ "dependencies": {
+ "@mapbox/mapbox-gl-style-spec": "^13.23.1",
+ "mapbox-to-css-font": "^2.4.1"
+ }
+ },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -9028,6 +9183,11 @@
"node": ">=6"
}
},
+ "node_modules/parse-headers": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
+ "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA=="
+ },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -9226,6 +9386,18 @@
"node": ">=8"
}
},
+ "node_modules/pbf": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
+ "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
+ "dependencies": {
+ "ieee754": "^1.1.12",
+ "resolve-protobuf-schema": "^2.1.0"
+ },
+ "bin": {
+ "pbf": "bin/pbf"
+ }
+ },
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -9480,6 +9652,11 @@
"node": ">=10"
}
},
+ "node_modules/protocol-buffers-schema": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
+ "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -9562,6 +9739,22 @@
}
]
},
+ "node_modules/quick-lru": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.1.tgz",
+ "integrity": "sha512-S27GBT+F0NTRiehtbrgaSE1idUAJ5bX8dPAQTdylEyNlrdcH5X4Lz7Edz3DYzecbsCluD5zO8ZNEe04z3D3u6Q==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/quickselect": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
+ "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+ },
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -9595,6 +9788,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/rbush": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
+ "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
+ "dependencies": {
+ "quickselect": "^2.0.0"
+ }
+ },
"node_modules/read-package-json": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.3.tgz",
@@ -9837,6 +10038,14 @@
"node": ">=8"
}
},
+ "node_modules/resolve-protobuf-schema": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
+ "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+ "dependencies": {
+ "protocol-buffers-schema": "^3.3.1"
+ }
+ },
"node_modules/resolve-url-loader": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz",
@@ -10019,6 +10228,11 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
+ },
"node_modules/rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
@@ -10587,6 +10801,34 @@
"node": ">= 10"
}
},
+ "node_modules/sort-asc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz",
+ "integrity": "sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sort-desc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz",
+ "integrity": "sha512-jfZacW5SKOP97BF5rX5kQfJmRVZP5/adDUTY8fCSPvNcXDVpUEe2pr/iKGlcyZzchRJZrswnp68fgk3qBXgkJw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sort-object": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz",
+ "integrity": "sha512-aAQiEdqFTTdsvUFxXm3umdo04J7MRljoVGbBlkH7BgNsMvVNAJyGj7C/wV1A8wHWAJj/YikeZbfuCKqhggNWGA==",
+ "dependencies": {
+ "sort-asc": "^0.1.0",
+ "sort-desc": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
@@ -11608,6 +11850,11 @@
"defaults": "^1.0.3"
}
},
+ "node_modules/web-worker": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
+ "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA=="
+ },
"node_modules/webpack": {
"version": "5.80.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz",
@@ -12056,6 +12303,11 @@
}
}
},
+ "node_modules/xml-utils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.7.0.tgz",
+ "integrity": "sha512-bWB489+RQQclC7A9OW8e5BzbT8Tu//jtAOvkYwewFr+Q9T9KDGvfzC1lp0pYPEQPEoPQLDkmxkepSC/2gIAZGw=="
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/apps/frontend/package.json b/apps/frontend/package.json
index 8112696..2b36dc3 100644
--- a/apps/frontend/package.json
+++ b/apps/frontend/package.json
@@ -21,6 +21,10 @@
"@fortawesome/angular-fontawesome": "^0.13.0",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
+ "@ngrx/effects": "^16.0.0",
+ "@ngrx/store": "^16.0.0",
+ "@ngrx/store-devtools": "^16.0.0",
+ "ol": "^7.3.0",
"primeng": "^16.0.0-rc.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@@ -39,4 +43,4 @@
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~5.0.2"
}
-}
+}
\ No newline at end of file
diff --git a/apps/frontend/src/app/app-routing.module.ts b/apps/frontend/src/app/app-routing.module.ts
index 0297262..2d785d3 100644
--- a/apps/frontend/src/app/app-routing.module.ts
+++ b/apps/frontend/src/app/app-routing.module.ts
@@ -1,10 +1,16 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
-const routes: Routes = [];
+const routes: Routes = [
+ {
+ path: '',
+ loadChildren: () =>
+ import('./modules/map/map.module').then((m) => m.MapModule),
+ },
+];
@NgModule({
imports: [RouterModule.forRoot(routes)],
- exports: [RouterModule]
+ exports: [RouterModule],
})
-export class AppRoutingModule { }
+export class AppRoutingModule {}
diff --git a/apps/frontend/src/app/app.component.html b/apps/frontend/src/app/app.component.html
index 2a0fbf1..0680b43 100644
--- a/apps/frontend/src/app/app.component.html
+++ b/apps/frontend/src/app/app.component.html
@@ -1,484 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ title }} app is running!
-
-
-
-
-
-
-
Resources
-
Here are some links to help you get started:
-
-
-
-
-
Next Steps
-
What do you want to do next with your app?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
ng generate component xyz
-
ng add @angular/material
-
ng add @angular/pwa
-
ng add _____
-
ng test
-
ng build
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/app/app.module.ts b/apps/frontend/src/app/app.module.ts
index 37f523e..c95b849 100644
--- a/apps/frontend/src/app/app.module.ts
+++ b/apps/frontend/src/app/app.module.ts
@@ -1,20 +1,28 @@
-import { NgModule } from '@angular/core';
+import { NgModule, isDevMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
+import { HttpClientModule } from '@angular/common/http';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { EffectsModule } from '@ngrx/effects';
+import { StoreModule } from '@ngrx/store';
+import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
-import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { IssueEffect } from './store/effect/issue.effect';
+import { issueReducer } from './store/reducer/issue.reducer';
@NgModule({
- declarations: [
- AppComponent
- ],
+ declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
- FontAwesomeModule
+ FontAwesomeModule,
+ StoreModule.forRoot({ issueState: issueReducer }),
+ EffectsModule.forRoot([IssueEffect]),
+ HttpClientModule,
+ StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: !isDevMode() }),
],
providers: [],
- bootstrap: [AppComponent]
+ bootstrap: [AppComponent],
})
-export class AppModule { }
+export class AppModule {}
diff --git a/apps/frontend/src/app/models/issue.mock.ts b/apps/frontend/src/app/models/issue.mock.ts
new file mode 100644
index 0000000..e69de29
diff --git a/apps/frontend/src/app/models/issue.model.ts b/apps/frontend/src/app/models/issue.model.ts
new file mode 100644
index 0000000..5d31d7a
--- /dev/null
+++ b/apps/frontend/src/app/models/issue.model.ts
@@ -0,0 +1,10 @@
+export interface IssueModel {
+ id: string;
+ title: string;
+ cords: [number, number];
+ description: string;
+ status: 'new' | 'inprogress' | 'done';
+ photos: any[];
+ type: 'problem' | 'suggestion';
+ createdAt: Date;
+}
diff --git a/apps/frontend/src/app/modules/issue/issue-routing.module.ts b/apps/frontend/src/app/modules/issue/issue-routing.module.ts
new file mode 100644
index 0000000..941aecc
--- /dev/null
+++ b/apps/frontend/src/app/modules/issue/issue-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { IssueComponent } from './issue.component';
+
+const routes: Routes = [{ path: ':id', component: IssueComponent }];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class IssueRoutingModule {}
diff --git a/apps/frontend/src/app/modules/issue/issue.component.html b/apps/frontend/src/app/modules/issue/issue.component.html
new file mode 100644
index 0000000..e400e95
--- /dev/null
+++ b/apps/frontend/src/app/modules/issue/issue.component.html
@@ -0,0 +1,9 @@
+
+
+
+
+ {{ (issue$ | async)?.title }}
+
+
+
+
diff --git a/apps/frontend/src/app/modules/issue/issue.component.scss b/apps/frontend/src/app/modules/issue/issue.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/apps/frontend/src/app/modules/issue/issue.component.spec.ts b/apps/frontend/src/app/modules/issue/issue.component.spec.ts
new file mode 100644
index 0000000..6599c09
--- /dev/null
+++ b/apps/frontend/src/app/modules/issue/issue.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IssueComponent } from './issue.component';
+
+describe('IssueComponent', () => {
+ let component: IssueComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [IssueComponent]
+ });
+ fixture = TestBed.createComponent(IssueComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/apps/frontend/src/app/modules/issue/issue.component.ts b/apps/frontend/src/app/modules/issue/issue.component.ts
new file mode 100644
index 0000000..093dd42
--- /dev/null
+++ b/apps/frontend/src/app/modules/issue/issue.component.ts
@@ -0,0 +1,23 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Store } from '@ngrx/store';
+import { EMPTY, Observable } from 'rxjs';
+import { IssueModel } from 'src/app/models/issue.model';
+import { selectIssue } from 'src/app/store/selectors/issue.selectors';
+
+@Component({
+ selector: 'app-issue',
+ templateUrl: './issue.component.html',
+ styleUrls: ['./issue.component.scss'],
+})
+export class IssueComponent implements OnInit {
+ issue$: Observable = EMPTY;
+
+ constructor(private store: Store, private route: ActivatedRoute) {}
+
+ ngOnInit(): void {
+ this.route.params.subscribe((params) => {
+ this.issue$ = this.store.select(selectIssue(params['id']));
+ });
+ }
+}
diff --git a/apps/frontend/src/app/modules/issue/issue.module.ts b/apps/frontend/src/app/modules/issue/issue.module.ts
new file mode 100644
index 0000000..170dc41
--- /dev/null
+++ b/apps/frontend/src/app/modules/issue/issue.module.ts
@@ -0,0 +1,11 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { CardModule } from 'primeng/card';
+import { IssueComponent } from './issue.component';
+
+@NgModule({
+ declarations: [IssueComponent],
+ imports: [CommonModule, CardModule],
+ providers: [],
+})
+export class IssueModule {}
diff --git a/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.html b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.html
new file mode 100644
index 0000000..9dd3021
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.html
@@ -0,0 +1,3 @@
+
+ {{ issue.title }}
+
diff --git a/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.scss b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.spec.ts b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.spec.ts
new file mode 100644
index 0000000..2993759
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IssueElementComponent } from './issue-element.component';
+
+describe('IssueElementComponent', () => {
+ let component: IssueElementComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [IssueElementComponent]
+ });
+ fixture = TestBed.createComponent(IssueElementComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.ts b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.ts
new file mode 100644
index 0000000..ad930ea
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/components/issue-element/issue-element.component.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+import { IssueModel } from 'src/app/models/issue.model';
+
+@Component({
+ selector: 'app-issue-element',
+ templateUrl: './issue-element.component.html',
+ styleUrls: ['./issue-element.component.scss'],
+})
+export class IssueElementComponent {
+ @Input() issue!: IssueModel;
+}
diff --git a/apps/frontend/src/app/modules/issues/issue.component.html b/apps/frontend/src/app/modules/issues/issue.component.html
new file mode 100644
index 0000000..369a761
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/issue.component.html
@@ -0,0 +1,6 @@
+
diff --git a/apps/frontend/src/app/modules/issues/issue.component.scss b/apps/frontend/src/app/modules/issues/issue.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/apps/frontend/src/app/modules/issues/issue.component.spec.ts b/apps/frontend/src/app/modules/issues/issue.component.spec.ts
new file mode 100644
index 0000000..6599c09
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/issue.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IssueComponent } from './issue.component';
+
+describe('IssueComponent', () => {
+ let component: IssueComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [IssueComponent]
+ });
+ fixture = TestBed.createComponent(IssueComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/apps/frontend/src/app/modules/issues/issue.component.ts b/apps/frontend/src/app/modules/issues/issue.component.ts
new file mode 100644
index 0000000..ed465c7
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/issue.component.ts
@@ -0,0 +1,21 @@
+import { Component, OnInit } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { EMPTY, Observable } from 'rxjs';
+import { IssueModel } from 'src/app/models/issue.model';
+import { receiveAllIssuesAction } from 'src/app/store/actions/issue.actions';
+import { selectAllIssues } from 'src/app/store/selectors/issue.selectors';
+
+@Component({
+ selector: 'app-issue',
+ templateUrl: './issue.component.html',
+ styleUrls: ['./issue.component.scss'],
+})
+export class IssueComponent implements OnInit {
+ issues$: Observable = EMPTY;
+ constructor(private store: Store) {}
+
+ ngOnInit(): void {
+ this.store.dispatch(receiveAllIssuesAction());
+ this.issues$ = this.store.select(selectAllIssues);
+ }
+}
diff --git a/apps/frontend/src/app/modules/issues/issue.module.ts b/apps/frontend/src/app/modules/issues/issue.module.ts
new file mode 100644
index 0000000..6e99fca
--- /dev/null
+++ b/apps/frontend/src/app/modules/issues/issue.module.ts
@@ -0,0 +1,13 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { CardModule } from 'primeng/card';
+import { IssueElementComponent } from './components/issue-element/issue-element.component';
+import { IssueComponent } from './issue.component';
+
+@NgModule({
+ declarations: [IssueComponent, IssueElementComponent],
+ imports: [CommonModule, CardModule],
+ exports: [IssueComponent],
+ providers: [],
+})
+export class IssueModule {}
diff --git a/apps/frontend/src/app/modules/map/map-routing.module.ts b/apps/frontend/src/app/modules/map/map-routing.module.ts
new file mode 100644
index 0000000..22c9c8c
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { MapComponent } from './map.component';
+
+const routes: Routes = [{ path: '', component: MapComponent }];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class MapRoutingModule {}
diff --git a/apps/frontend/src/app/modules/map/map.component.html b/apps/frontend/src/app/modules/map/map.component.html
new file mode 100644
index 0000000..2935fe9
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map.component.html
@@ -0,0 +1,4 @@
+
+
diff --git a/apps/frontend/src/app/modules/map/map.component.scss b/apps/frontend/src/app/modules/map/map.component.scss
new file mode 100644
index 0000000..2a24f2f
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map.component.scss
@@ -0,0 +1,9 @@
+#map {
+ width: 100%;
+ height: 800px;
+}
+.issues {
+ position: relative;
+ top: -30px;
+ padding: 0 10px;
+}
diff --git a/apps/frontend/src/app/modules/map/map.component.spec.ts b/apps/frontend/src/app/modules/map/map.component.spec.ts
new file mode 100644
index 0000000..175a264
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MapComponent } from './map.component';
+
+describe('MapComponent', () => {
+ let component: MapComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [MapComponent]
+ });
+ fixture = TestBed.createComponent(MapComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/apps/frontend/src/app/modules/map/map.component.ts b/apps/frontend/src/app/modules/map/map.component.ts
new file mode 100644
index 0000000..0eee4ee
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map.component.ts
@@ -0,0 +1,63 @@
+import { Component, OnInit } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { Feature } from 'ol';
+import Map from 'ol/Map';
+import View from 'ol/View';
+import { Point } from 'ol/geom';
+import TileLayer from 'ol/layer/Tile';
+import VectorLayer from 'ol/layer/Vector';
+import * as olProj from 'ol/proj';
+import OSM from 'ol/source/OSM';
+import VectorSource from 'ol/source/Vector';
+import { tap } from 'rxjs';
+import { receiveAllIssuesAction } from 'src/app/store/actions/issue.actions';
+import { selectAllIssues } from 'src/app/store/selectors/issue.selectors';
+
+@Component({
+ selector: 'app-map',
+ templateUrl: './map.component.html',
+ styleUrls: ['./map.component.scss'],
+})
+export class MapComponent implements OnInit {
+ map!: Map;
+
+ constructor(private store: Store) {}
+
+ ngOnInit(): void {
+ this.map = new Map({
+ target: 'map',
+ layers: [
+ new TileLayer({
+ source: new OSM(),
+ }),
+ ],
+ view: new View({
+ center: olProj.fromLonLat([18.5518, 54.4065]),
+ zoom: 11,
+ }),
+ });
+
+ this.store.dispatch(receiveAllIssuesAction());
+ this.store
+ .select(selectAllIssues)
+ .pipe(
+ tap((issues) =>
+ issues.forEach((issue) => {
+ const pointLayer = new VectorLayer({
+ source: new VectorSource({
+ features: [
+ new Feature({
+ geometry: new Point(olProj.fromLonLat(issue.cords)),
+ }),
+ ],
+ }),
+ });
+ this.map.addLayer(pointLayer);
+ })
+ )
+ )
+ .subscribe((issues) => {
+ console.log(this.map, issues);
+ });
+ }
+}
diff --git a/apps/frontend/src/app/modules/map/map.module.ts b/apps/frontend/src/app/modules/map/map.module.ts
new file mode 100644
index 0000000..a26f10b
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/map.module.ts
@@ -0,0 +1,13 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ButtonModule } from 'primeng/button';
+import { IssueModule } from '../issues/issue.module';
+import { MapRoutingModule } from './map-routing.module';
+import { MapComponent } from './map.component';
+
+@NgModule({
+ declarations: [MapComponent],
+ imports: [CommonModule, MapRoutingModule, IssueModule, ButtonModule],
+ providers: [],
+})
+export class MapModule {}
diff --git a/apps/frontend/src/app/modules/map/services/points.service.ts b/apps/frontend/src/app/modules/map/services/points.service.ts
new file mode 100644
index 0000000..4343f3d
--- /dev/null
+++ b/apps/frontend/src/app/modules/map/services/points.service.ts
@@ -0,0 +1,6 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class PointService {}
diff --git a/apps/frontend/src/app/services/issues.service.ts b/apps/frontend/src/app/services/issues.service.ts
new file mode 100644
index 0000000..859f4a5
--- /dev/null
+++ b/apps/frontend/src/app/services/issues.service.ts
@@ -0,0 +1,39 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { map } from 'rxjs';
+import { IssueModel } from '../models/issue.model';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class IssueService {
+ constructor(private http: HttpClient) {}
+
+ getIssues() {
+ return this.http.get('/issues').pipe(
+ map((issues) =>
+ issues.map((issue) => ({
+ id: issue.id,
+ createdAt: new Date(issue.createdAt),
+ cords: [issue.latitude, issue.longitude],
+ description: issue.description,
+ photos: [],
+ status: issue.status as 'new' | 'inprogress' | 'done',
+ title: issue.title,
+ type: issue.type as 'problem' | 'suggestion',
+ }))
+ )
+ );
+ }
+}
+
+interface IssueDto {
+ id: string;
+ title: string;
+ type: string;
+ status: string;
+ description: string;
+ latitude: number;
+ longitude: number;
+ createdAt: string;
+}
diff --git a/apps/frontend/src/app/store/actions/issue.actions.ts b/apps/frontend/src/app/store/actions/issue.actions.ts
new file mode 100644
index 0000000..fd488aa
--- /dev/null
+++ b/apps/frontend/src/app/store/actions/issue.actions.ts
@@ -0,0 +1,13 @@
+import { createAction, props } from '@ngrx/store';
+import { IssueModel } from 'src/app/models/issue.model';
+
+export const receiveAllIssuesAction = createAction(
+ '[issues] receive all issues'
+);
+export const receivedAllIssuesSuccessAction = createAction(
+ '[issues] received all issues success',
+ props<{ issues: IssueModel[] }>()
+);
+export const receivedAllIssuesErrorAction = createAction(
+ '[issues] received all issues error'
+);
diff --git a/apps/frontend/src/app/store/effect/issue.effect.ts b/apps/frontend/src/app/store/effect/issue.effect.ts
new file mode 100644
index 0000000..5030881
--- /dev/null
+++ b/apps/frontend/src/app/store/effect/issue.effect.ts
@@ -0,0 +1,25 @@
+import { Injectable } from '@angular/core';
+import { Actions, createEffect, ofType } from '@ngrx/effects';
+import { first, switchMap } from 'rxjs';
+import { IssueModel } from 'src/app/models/issue.model';
+import { IssueService } from 'src/app/services/issues.service';
+import {
+ receiveAllIssuesAction,
+ receivedAllIssuesSuccessAction,
+} from '../actions/issue.actions';
+
+@Injectable({ providedIn: 'root' })
+export class IssueEffect {
+ preloadAutomaticOffer$ = createEffect(() => {
+ return this.actions$.pipe(
+ ofType(receiveAllIssuesAction),
+ switchMap((action) => this.issueService.getIssues()),
+ switchMap((issues: IssueModel[]) => [
+ receivedAllIssuesSuccessAction({ issues }),
+ ]),
+ first()
+ );
+ });
+
+ constructor(private actions$: Actions, private issueService: IssueService) {}
+}
diff --git a/apps/frontend/src/app/store/reducer/issue.reducer.ts b/apps/frontend/src/app/store/reducer/issue.reducer.ts
new file mode 100644
index 0000000..99d746f
--- /dev/null
+++ b/apps/frontend/src/app/store/reducer/issue.reducer.ts
@@ -0,0 +1,45 @@
+import { createReducer, on } from '@ngrx/store';
+import { receivedAllIssuesSuccessAction } from '../actions/issue.actions';
+import { IssueState } from '../state/issue.state';
+
+const initialState: IssueState = {
+ issues: [
+ {
+ id: '1',
+ cords: [18.57187, 54.40984],
+ title: 'Dziura w drodze na Oliwi',
+ createdAt: new Date(),
+ description: 'Wielka dziura',
+ photos: [],
+ status: 'new',
+ type: 'problem',
+ },
+ {
+ id: '2',
+ cords: [18.58080765011577, 54.41806822519011],
+ title: 'Dziura w drodze na Żabiance',
+ createdAt: new Date(),
+ description: 'Wielka dziura',
+ photos: [],
+ status: 'new',
+ type: 'problem',
+ },
+ {
+ id: '3',
+ cords: [18.611836200396905, 54.405856587640585],
+ title: 'Dziura w drodze na Nigdzie',
+ createdAt: new Date(),
+ description: 'Wielka dziura',
+ photos: [],
+ status: 'new',
+ type: 'problem',
+ },
+ ],
+};
+
+export const issueReducer = createReducer(
+ initialState,
+ on(receivedAllIssuesSuccessAction, (state: IssueState, action) => ({
+ issues: action.issues,
+ }))
+);
diff --git a/apps/frontend/src/app/store/selectors/issue.selectors.ts b/apps/frontend/src/app/store/selectors/issue.selectors.ts
new file mode 100644
index 0000000..aa4684f
--- /dev/null
+++ b/apps/frontend/src/app/store/selectors/issue.selectors.ts
@@ -0,0 +1,9 @@
+import { createFeatureSelector, createSelector } from '@ngrx/store';
+import { IssueState } from '../state/issue.state';
+
+const selectIssueFeatureState = createFeatureSelector('issueState');
+
+export const selectAllIssues = createSelector(
+ selectIssueFeatureState,
+ (state) => state.issues
+);
diff --git a/apps/frontend/src/app/store/state/issue.state.ts b/apps/frontend/src/app/store/state/issue.state.ts
new file mode 100644
index 0000000..6d871fa
--- /dev/null
+++ b/apps/frontend/src/app/store/state/issue.state.ts
@@ -0,0 +1,5 @@
+import { IssueModel } from 'src/app/models/issue.model';
+
+export interface IssueState {
+ issues: IssueModel[];
+}
diff --git a/apps/frontend/src/index.html b/apps/frontend/src/index.html
index 3af61ec..dbc0cf9 100644
--- a/apps/frontend/src/index.html
+++ b/apps/frontend/src/index.html
@@ -1,13 +1,19 @@
-
+
-
-
- Frontend
-
-
-
-
-
-
-
+
+
+ Frontend
+
+
+
+
+
+
+
+
+