Hello, {{ title }}
229 |Congratulations! Your app is running. 🎉
230 |├── LICENSE
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── public
└── favicon.ico
├── src
├── app
│ ├── app.config.ts
│ ├── app.html
│ ├── app.routes.ts
│ ├── app.scss
│ ├── app.spec.ts
│ ├── app.ts
│ ├── components
│ │ ├── donor-form
│ │ │ ├── donor-form.html
│ │ │ ├── donor-form.scss
│ │ │ ├── donor-form.spec.ts
│ │ │ └── donor-form.ts
│ │ └── map
│ │ │ ├── map.html
│ │ │ ├── map.scss
│ │ │ ├── map.spec.ts
│ │ │ └── map.ts
│ ├── donor.service.ts
│ └── firebase-config.ts
├── index.html
├── main.ts
└── styles.scss
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Didin Jamaludin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Build a Real-Time Blood Donor App with Angular 20, Google Maps, and Firebase
2 |
3 | Read full article [here](https://www.djamware.com/post/5d70d6608ff935a40f438f3a/build-a-realtime-blood-donor-app-with-angular-20-google-maps-and-firebase).
4 |
5 | This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.0.
6 |
7 | ## Development server
8 |
9 | To start a local development server, run:
10 |
11 | ```bash
12 | ng serve
13 | ```
14 |
15 | Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
16 |
17 | ## Code scaffolding
18 |
19 | Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
20 |
21 | ```bash
22 | ng generate component component-name
23 | ```
24 |
25 | For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
26 |
27 | ```bash
28 | ng generate --help
29 | ```
30 |
31 | ## Building
32 |
33 | To build the project run:
34 |
35 | ```bash
36 | ng build
37 | ```
38 |
39 | This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
40 |
41 | ## Running unit tests
42 |
43 | To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
44 |
45 | ```bash
46 | ng test
47 | ```
48 |
49 | ## Running end-to-end tests
50 |
51 | For end-to-end (e2e) testing, run:
52 |
53 | ```bash
54 | ng e2e
55 | ```
56 |
57 | Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
58 |
59 | ## Additional Resources
60 |
61 | For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
62 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "blood-donor-app": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:component": {
10 | "style": "scss"
11 | }
12 | },
13 | "root": "",
14 | "sourceRoot": "src",
15 | "prefix": "app",
16 | "architect": {
17 | "build": {
18 | "builder": "@angular/build:application",
19 | "options": {
20 | "browser": "src/main.ts",
21 | "polyfills": [
22 | "zone.js"
23 | ],
24 | "tsConfig": "tsconfig.app.json",
25 | "inlineStyleLanguage": "scss",
26 | "assets": [
27 | {
28 | "glob": "**/*",
29 | "input": "public"
30 | }
31 | ],
32 | "styles": [
33 | "@angular/material/prebuilt-themes/azure-blue.css",
34 | "src/styles.scss"
35 | ]
36 | },
37 | "configurations": {
38 | "production": {
39 | "budgets": [
40 | {
41 | "type": "initial",
42 | "maximumWarning": "500kB",
43 | "maximumError": "1MB"
44 | },
45 | {
46 | "type": "anyComponentStyle",
47 | "maximumWarning": "4kB",
48 | "maximumError": "8kB"
49 | }
50 | ],
51 | "outputHashing": "all"
52 | },
53 | "development": {
54 | "optimization": false,
55 | "extractLicenses": false,
56 | "sourceMap": true
57 | }
58 | },
59 | "defaultConfiguration": "production"
60 | },
61 | "serve": {
62 | "builder": "@angular/build:dev-server",
63 | "configurations": {
64 | "production": {
65 | "buildTarget": "blood-donor-app:build:production"
66 | },
67 | "development": {
68 | "buildTarget": "blood-donor-app:build:development"
69 | }
70 | },
71 | "defaultConfiguration": "development"
72 | },
73 | "extract-i18n": {
74 | "builder": "@angular/build:extract-i18n"
75 | },
76 | "test": {
77 | "builder": "@angular/build:karma",
78 | "options": {
79 | "polyfills": [
80 | "zone.js",
81 | "zone.js/testing"
82 | ],
83 | "tsConfig": "tsconfig.spec.json",
84 | "inlineStyleLanguage": "scss",
85 | "assets": [
86 | {
87 | "glob": "**/*",
88 | "input": "public"
89 | }
90 | ],
91 | "styles": [
92 | "@angular/material/prebuilt-themes/azure-blue.css",
93 | "src/styles.scss"
94 | ]
95 | }
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blood-donor-app",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "watch": "ng build --watch --configuration development",
9 | "test": "ng test"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@angular/cdk": "^20.0.1",
14 | "@angular/common": "^20.0.0",
15 | "@angular/compiler": "^20.0.0",
16 | "@angular/core": "^20.0.0",
17 | "@angular/fire": "^20.0.0",
18 | "@angular/forms": "^20.0.0",
19 | "@angular/google-maps": "^20.0.1",
20 | "@angular/material": "^20.0.1",
21 | "@angular/platform-browser": "^20.0.0",
22 | "@angular/router": "^20.0.0",
23 | "firebase": "^11.8.1",
24 | "rxjs": "~7.8.0",
25 | "tslib": "^2.3.0",
26 | "zone.js": "~0.15.0"
27 | },
28 | "devDependencies": {
29 | "@angular/build": "^20.0.0",
30 | "@angular/cli": "^20.0.0",
31 | "@angular/compiler-cli": "^20.0.0",
32 | "@types/jasmine": "~5.1.0",
33 | "jasmine-core": "~5.7.0",
34 | "karma": "~6.4.0",
35 | "karma-chrome-launcher": "~3.2.0",
36 | "karma-coverage": "~2.2.0",
37 | "karma-jasmine": "~5.1.0",
38 | "karma-jasmine-html-reporter": "~2.1.0",
39 | "typescript": "~5.8.2"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/didinj/angular-8-google-maps-firebase-realtime/9573b7551a2b153c9bdda8827483a33c7bc7f219/public/favicon.ico
--------------------------------------------------------------------------------
/src/app/app.config.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationConfig, importProvidersFrom, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
2 | import { provideRouter } from '@angular/router';
3 |
4 | import { routes } from './app.routes';
5 | import { firebaseConfig } from './firebase-config';
6 | import { initializeApp } from 'firebase/app';
7 | import { provideDatabase, getDatabase } from '@angular/fire/database';
8 | import { provideAnimations } from '@angular/platform-browser/animations';
9 | import { GoogleMapsModule } from '@angular/google-maps';
10 |
11 | export const appConfig: ApplicationConfig = {
12 | providers: [
13 | provideBrowserGlobalErrorListeners(),
14 | provideZoneChangeDetection({ eventCoalescing: true }),
15 | provideRouter(routes),
16 | provideFirebaseApp(() => initializeApp(firebaseConfig)),
17 | provideDatabase(() => getDatabase()),
18 | provideAnimations(),
19 | importProvidersFrom(GoogleMapsModule),
20 | ]
21 | };
22 | function provideFirebaseApp(arg0: () => any): import("@angular/core").Provider | import("@angular/core").EnvironmentProviders {
23 | throw new Error('Function not implemented.');
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/app/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
179 |
180 | Congratulations! Your app is running. 🎉Hello, {{ title }}
229 |