mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 04:43:03 -05:00
fix: run prettier on all file to avoid prettier issue inside PR
This commit is contained in:
@@ -5,6 +5,8 @@ import { RouterOutlet } from '@angular/router';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <router-outlet></router-outlet> `,
|
template: `
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { NavButtonComponent } from './nav-button.component';
|
|||||||
selector: 'app-foo',
|
selector: 'app-foo',
|
||||||
template: `
|
template: `
|
||||||
Welcome to foo page
|
Welcome to foo page
|
||||||
<nav-button href="home" class="fixed top-3 left-1/2">Home Page</nav-button>
|
<nav-button href="home" class="fixed left-1/2 top-3">Home Page</nav-button>
|
||||||
<div class="h-screen bg-blue-200">section 1</div>
|
<div class="h-screen bg-blue-200">section 1</div>
|
||||||
<div class="h-screen bg-red-200">section 2</div>
|
<div class="h-screen bg-red-200">section 2</div>
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { NavButtonComponent } from './nav-button.component';
|
|||||||
imports: [NavButtonComponent],
|
imports: [NavButtonComponent],
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
template: `
|
template: `
|
||||||
<nav-button href="/foo" class="fixed top-3 left-1/2">Foo Page</nav-button>
|
<nav-button href="/foo" class="fixed left-1/2 top-3">Foo Page</nav-button>
|
||||||
<div id="top" class="h-screen bg-gray-500">
|
<div id="top" class="h-screen bg-gray-500">
|
||||||
Empty
|
Empty
|
||||||
<nav-button href="#bottom">Scroll Bottom</nav-button>
|
<nav-button href="#bottom">Scroll Bottom</nav-button>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { RouterOutlet } from '@angular/router';
|
|||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<h1 class="text-xl px-4 py-2">My Application</h1>
|
<h1 class="px-4 py-2 text-xl">My Application</h1>
|
||||||
<section class="flex">
|
<section class="flex">
|
||||||
<router-outlet name="side" />
|
<router-outlet name="side" />
|
||||||
<div class="border p-4">
|
<div class="border p-4">
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bar',
|
selector: 'app-bar',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
template: ` BarComponent `,
|
template: `
|
||||||
|
BarComponent
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class BarComponent {}
|
export class BarComponent {}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-foo',
|
selector: 'app-foo',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
template: `Foo Component `,
|
template: `
|
||||||
|
Foo Component
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class FooComponent {}
|
export class FooComponent {}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface MenuItem {
|
|||||||
template: `
|
template: `
|
||||||
<ng-container *ngFor="let menu of menus">
|
<ng-container *ngFor="let menu of menus">
|
||||||
<a
|
<a
|
||||||
class="border px-4 py-2 rounded-md"
|
class="rounded-md border px-4 py-2"
|
||||||
[routerLink]="menu.path"
|
[routerLink]="menu.path"
|
||||||
routerLinkActive="isSelected">
|
routerLinkActive="isSelected">
|
||||||
{{ menu.name }}
|
{{ menu.name }}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,11 +17,10 @@ import {
|
|||||||
*ngTemplateOutlet="
|
*ngTemplateOutlet="
|
||||||
listTemplateRef || emptyRef;
|
listTemplateRef || emptyRef;
|
||||||
context: { $implicit: item, appList: item, index: i }
|
context: { $implicit: item, appList: item, index: i }
|
||||||
">
|
"></ng-container>
|
||||||
</ng-container>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template #emptyRef> No Template </ng-template>
|
<ng-template #emptyRef>No Template</ng-template>
|
||||||
`,
|
`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ interface Person {
|
|||||||
context: { $implicit: person.name, age: person.age }
|
context: { $implicit: person.name, age: person.age }
|
||||||
"></ng-container>
|
"></ng-container>
|
||||||
|
|
||||||
<ng-template #emptyRef> No Template </ng-template>
|
<ng-template #emptyRef>No Template</ng-template>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class PersonComponent {
|
export class PersonComponent {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export class AppComponent implements OnInit {
|
|||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json; charset=UTF-8',
|
'Content-type': 'application/json; charset=UTF-8',
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.subscribe((todoUpdated: any) => {
|
.subscribe((todoUpdated: any) => {
|
||||||
this.todos[todoUpdated.id - 1] = todoUpdated;
|
this.todos[todoUpdated.id - 1] = todoUpdated;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
|
||||||
import { enableProdMode, importProvidersFrom } from '@angular/core';
|
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [importProvidersFrom(HttpClientModule)],
|
providers: [importProvidersFrom(HttpClientModule)],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ import { bootstrapApplication } from '@angular/platform-browser';
|
|||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Component } from '@angular/core';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [BtnDisabledDirective, BtnHelmetDirective],
|
imports: [BtnDisabledDirective, BtnHelmetDirective],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <button btnDisabled hlm>Coucou</button> `,
|
template: `
|
||||||
|
<button btnDisabled hlm>Coucou</button>
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface ProductContext {
|
|||||||
export class ProductDirective {
|
export class ProductDirective {
|
||||||
static ngTemplateContextGuard(
|
static ngTemplateContextGuard(
|
||||||
dir: ProductDirective,
|
dir: ProductDirective,
|
||||||
ctx: unknown
|
ctx: unknown,
|
||||||
): ctx is ProductContext {
|
): ctx is ProductContext {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export class CurrencyPipe implements PipeTransform {
|
|||||||
|
|
||||||
transform(price: number) {
|
transform(price: number) {
|
||||||
return this.currencyService.symbol$.pipe(
|
return this.currencyService.symbol$.pipe(
|
||||||
map((s) => `${String(price)}${s}`)
|
map((s) => `${String(price)}${s}`),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const currency: Currency[] = [
|
|||||||
export class CurrencyService extends ComponentStore<{ code: string }> {
|
export class CurrencyService extends ComponentStore<{ code: string }> {
|
||||||
readonly code$ = this.select((state) => state.code);
|
readonly code$ = this.select((state) => state.code);
|
||||||
readonly symbol$ = this.code$.pipe(
|
readonly symbol$ = this.code$.pipe(
|
||||||
map((code) => currency.find((c) => c.code === code)?.symbol ?? code)
|
map((code) => currency.find((c) => c.code === code)?.symbol ?? code),
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -5,15 +5,17 @@ import { RouterLink, RouterOutlet } from '@angular/router';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterOutlet, RouterLink],
|
imports: [RouterOutlet, RouterLink],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <div class="flex gap-4 mb-5">
|
template: `
|
||||||
<button class="border rounded-md px-4 py-2" routerLink="video">
|
<div class="mb-5 flex gap-4">
|
||||||
|
<button class="rounded-md border px-4 py-2" routerLink="video">
|
||||||
Video
|
Video
|
||||||
</button>
|
</button>
|
||||||
<button class="border rounded-md px-4 py-2" routerLink="phone">
|
<button class="rounded-md border px-4 py-2" routerLink="phone">
|
||||||
Phone
|
Phone
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<router-outlet />`,
|
<router-outlet />
|
||||||
|
`,
|
||||||
host: {
|
host: {
|
||||||
class: 'p-10 flex flex-col',
|
class: 'p-10 flex flex-col',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import { TimerContainerComponent } from './timer-container.component';
|
|||||||
selector: 'app-phone',
|
selector: 'app-phone',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TimerContainerComponent],
|
imports: [TimerContainerComponent],
|
||||||
template: `<div class="flex gap-2">
|
template: `
|
||||||
|
<div class="flex gap-2">
|
||||||
Phone Call Timer:
|
Phone Call Timer:
|
||||||
<p class="italic">(should be 2000s)</p>
|
<p class="italic">(should be 2000s)</p>
|
||||||
</div>
|
</div>
|
||||||
<timer-container />`,
|
<timer-container />
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export default class PhoneComponent {}
|
export default class PhoneComponent {}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { DEFAULT_TIMER } from './data';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'timer',
|
selector: 'timer',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
template: ` Timer running {{ timer() }} `,
|
template: `
|
||||||
|
Timer running {{ timer() }}
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class TimerComponent {
|
export class TimerComponent {
|
||||||
timer = toSignal(interval(DEFAULT_TIMER));
|
timer = toSignal(interval(DEFAULT_TIMER));
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import { TimerContainerComponent } from './timer-container.component';
|
|||||||
selector: 'app-video',
|
selector: 'app-video',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TimerContainerComponent],
|
imports: [TimerContainerComponent],
|
||||||
template: `<div class="flex gap-2">
|
template: `
|
||||||
|
<div class="flex gap-2">
|
||||||
Video Call Timer:
|
Video Call Timer:
|
||||||
<p class="italic">(should be the default 1000s)</p>
|
<p class="italic">(should be the default 1000s)</p>
|
||||||
</div>
|
</div>
|
||||||
<timer-container />`,
|
<timer-container />
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export default class VideoComponent {}
|
export default class VideoComponent {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { RouterOutlet } from '@angular/router';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `<router-outlet />`,
|
template: `
|
||||||
|
<router-outlet />
|
||||||
|
`,
|
||||||
styles: [''],
|
styles: [''],
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const appConfig: ApplicationConfig = {
|
|||||||
redirectTo: '',
|
redirectTo: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
withComponentInputBinding()
|
withComponentInputBinding(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,13 +9,25 @@ import { Photo } from '../photo.model';
|
|||||||
imports: [DatePipe, RouterLink],
|
imports: [DatePipe, RouterLink],
|
||||||
template: `
|
template: `
|
||||||
<img src="{{ photo.url_m }}" alt="{{ photo.title }}" class="image" />
|
<img src="{{ photo.url_m }}" alt="{{ photo.title }}" class="image" />
|
||||||
<p><span class="font-bold">Title:</span> {{ photo.title }}</p>
|
<p>
|
||||||
<p><span class="font-bold">Owner:</span> {{ photo.ownername }}</p>
|
<span class="font-bold">Title:</span>
|
||||||
<p><span class="font-bold">Date:</span> {{ photo.datetaken | date }}</p>
|
{{ photo.title }}
|
||||||
<p><span class="font-bold">Tags:</span> {{ photo.tags }}</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="font-bold">Owner:</span>
|
||||||
|
{{ photo.ownername }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="font-bold">Date:</span>
|
||||||
|
{{ photo.datetaken | date }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="font-bold">Tags:</span>
|
||||||
|
{{ photo.tags }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="border border-black rounded-md px-4 py-2 mt-10"
|
class="mt-10 rounded-md border border-black px-4 py-2"
|
||||||
routerLink="">
|
routerLink="">
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class PhotoStore
|
|||||||
private readonly endOfPage$ = this.select(
|
private readonly endOfPage$ = this.select(
|
||||||
this.page$,
|
this.page$,
|
||||||
this.pages$,
|
this.pages$,
|
||||||
(page, pages) => page === pages
|
(page, pages) => page === pages,
|
||||||
);
|
);
|
||||||
|
|
||||||
readonly vm$ = this.select(
|
readonly vm$ = this.select(
|
||||||
@@ -60,7 +60,7 @@ export class PhotoStore
|
|||||||
loading: this.loading$,
|
loading: this.loading$,
|
||||||
error: this.error$,
|
error: this.error$,
|
||||||
},
|
},
|
||||||
{ debounce: true }
|
{ debounce: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
ngrxOnStoreInit() {
|
ngrxOnStoreInit() {
|
||||||
@@ -82,7 +82,7 @@ export class PhotoStore
|
|||||||
this.select({
|
this.select({
|
||||||
search: this.search$,
|
search: this.search$,
|
||||||
page: this.page$,
|
page: this.page$,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,21 +91,21 @@ export class PhotoStore
|
|||||||
...state,
|
...state,
|
||||||
search,
|
search,
|
||||||
page: 1,
|
page: 1,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
readonly nextPage = this.updater(
|
readonly nextPage = this.updater(
|
||||||
(state): PhotoState => ({
|
(state): PhotoState => ({
|
||||||
...state,
|
...state,
|
||||||
page: state.page + 1,
|
page: state.page + 1,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
readonly previousPage = this.updater(
|
readonly previousPage = this.updater(
|
||||||
(state): PhotoState => ({
|
(state): PhotoState => ({
|
||||||
...state,
|
...state,
|
||||||
page: state.page - 1,
|
page: state.page - 1,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
readonly searchPhotos = this.effect<{ search: string; page: number }>(
|
readonly searchPhotos = this.effect<{ search: string; page: number }>(
|
||||||
@@ -123,13 +123,13 @@ export class PhotoStore
|
|||||||
});
|
});
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
PHOTO_STATE_KEY,
|
PHOTO_STATE_KEY,
|
||||||
JSON.stringify({ search, page })
|
JSON.stringify({ search, page }),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
(error: unknown) => this.patchState({ error, loading: false })
|
(error: unknown) => this.patchState({ error, loading: false }),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class PhotoService {
|
|||||||
|
|
||||||
public searchPublicPhotos(
|
public searchPublicPhotos(
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
page: number
|
page: number,
|
||||||
): Observable<FlickrAPIResponse> {
|
): Observable<FlickrAPIResponse> {
|
||||||
return this.http.get<FlickrAPIResponse>(
|
return this.http.get<FlickrAPIResponse>(
|
||||||
'https://www.flickr.com/services/rest/',
|
'https://www.flickr.com/services/rest/',
|
||||||
@@ -33,7 +33,7 @@ export class PhotoService {
|
|||||||
extras: 'tags,date_taken,owner_name,url_q,url_m',
|
extras: 'tags,date_taken,owner_name,url_q,url_m',
|
||||||
api_key: 'c3050d39a5bb308d9921bef0e15c437d',
|
api_key: 'c3050d39a5bb308d9921bef0e15c437d',
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,24 +2,26 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <div class="flex gap-2">
|
template: `
|
||||||
|
<div class="flex gap-2">
|
||||||
<button
|
<button
|
||||||
routerLink="home"
|
routerLink="home"
|
||||||
class="border px-4 py-2 border-blue-400 rounded-md">
|
class="rounded-md border border-blue-400 px-4 py-2">
|
||||||
Home
|
Home
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
routerLink="admin"
|
routerLink="admin"
|
||||||
class="border px-4 py-2 border-blue-400 rounded-md">
|
class="rounded-md border border-blue-400 px-4 py-2">
|
||||||
Admin
|
Admin
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
routerLink="user"
|
routerLink="user"
|
||||||
class="border px-4 py-2 border-blue-400 rounded-md">
|
class="rounded-md border border-blue-400 px-4 py-2">
|
||||||
User
|
User
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<router-outlet></router-outlet>`,
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
host: {
|
host: {
|
||||||
class: 'flex flex-col p-4 gap-3',
|
class: 'flex flex-col p-4 gap-3',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { RouterOutlet } from '@angular/router';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <router-outlet></router-outlet> `,
|
template: `
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
styles: [],
|
styles: [],
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
selector: 'button[app-button]',
|
selector: 'button[app-button]',
|
||||||
template: `<ng-content></ng-content>`,
|
template: `
|
||||||
|
<ng-content></ng-content>
|
||||||
|
`,
|
||||||
host: {
|
host: {
|
||||||
class: 'border border-blue-700 bg-blue-400 p-2 rounded-sm text-white',
|
class: 'border border-blue-700 bg-blue-400 p-2 rounded-sm text-white',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const APP_ROUTES = [
|
|||||||
path: 'enter',
|
path: 'enter',
|
||||||
loadComponent: () =>
|
loadComponent: () =>
|
||||||
import('./dashboard/admin.component').then(
|
import('./dashboard/admin.component').then(
|
||||||
(m) => m.AdminDashboardComponent
|
(m) => m.AdminDashboardComponent,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ import { appConfig } from './app/app.config';
|
|||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import { CardComponent } from '../../ui/card/card.component';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-student-card',
|
selector: 'app-student-card',
|
||||||
template: `<app-card
|
template: `
|
||||||
[list]="students"
|
<app-card
|
||||||
[type]="cardType"
|
[list]="students"
|
||||||
customClass="bg-light-green"></app-card>`,
|
[type]="cardType"
|
||||||
|
customClass="bg-light-green"></app-card>
|
||||||
|
`,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
styles: [
|
styles: [
|
||||||
`
|
`
|
||||||
@@ -25,7 +27,10 @@ export class StudentCardComponent implements OnInit {
|
|||||||
students: Student[] = [];
|
students: Student[] = [];
|
||||||
cardType = CardType.STUDENT;
|
cardType = CardType.STUDENT;
|
||||||
|
|
||||||
constructor(private http: FakeHttpService, private store: StudentStore) {}
|
constructor(
|
||||||
|
private http: FakeHttpService,
|
||||||
|
private store: StudentStore,
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
|
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import { CardComponent } from '../../ui/card/card.component';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-teacher-card',
|
selector: 'app-teacher-card',
|
||||||
template: `<app-card
|
template: `
|
||||||
[list]="teachers"
|
<app-card
|
||||||
[type]="cardType"
|
[list]="teachers"
|
||||||
customClass="bg-light-red"></app-card>`,
|
[type]="cardType"
|
||||||
|
customClass="bg-light-red"></app-card>
|
||||||
|
`,
|
||||||
styles: [
|
styles: [
|
||||||
`
|
`
|
||||||
::ng-deep .bg-light-red {
|
::ng-deep .bg-light-red {
|
||||||
@@ -25,7 +27,10 @@ export class TeacherCardComponent implements OnInit {
|
|||||||
teachers: Teacher[] = [];
|
teachers: Teacher[] = [];
|
||||||
cardType = CardType.TEACHER;
|
cardType = CardType.TEACHER;
|
||||||
|
|
||||||
constructor(private http: FakeHttpService, private store: TeacherStore) {}
|
constructor(
|
||||||
|
private http: FakeHttpService,
|
||||||
|
private store: TeacherStore,
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
|
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { CardType } from '../../model/card.model';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-item',
|
selector: 'app-list-item',
|
||||||
template: `
|
template: `
|
||||||
<div class="border border-grey-300 py-1 px-2 flex justify-between">
|
<div class="border-grey-300 flex justify-between border px-2 py-1">
|
||||||
{{ name }}
|
{{ name }}
|
||||||
<button (click)="delete(id)">
|
<button (click)="delete(id)">
|
||||||
<img class="h-5" src="assets/svg/trash.svg" />
|
<img class="h-5" src="assets/svg/trash.svg" />
|
||||||
@@ -22,7 +22,7 @@ export class ListItemComponent {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private teacherStore: TeacherStore,
|
private teacherStore: TeacherStore,
|
||||||
private studentStore: StudentStore
|
private studentStore: StudentStore,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
delete(id: number) {
|
delete(id: number) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { RouterLink, RouterModule } from '@angular/router';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterLink, RouterModule, ReactiveFormsModule],
|
imports: [RouterLink, RouterModule, ReactiveFormsModule],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: ` <label for="userName">UserName</label>
|
template: `
|
||||||
|
<label for="userName">UserName</label>
|
||||||
<input id="userName" type="text" [formControl]="userName" />
|
<input id="userName" type="text" [formControl]="userName" />
|
||||||
<label for="testId">TestId</label>
|
<label for="testId">TestId</label>
|
||||||
<input id="testId" type="number" [formControl]="testId" />
|
<input id="testId" type="number" [formControl]="testId" />
|
||||||
@@ -16,7 +17,8 @@ import { RouterLink, RouterModule } from '@angular/router';
|
|||||||
Test
|
Test
|
||||||
</button>
|
</button>
|
||||||
<button routerLink="/">HOME</button>
|
<button routerLink="/">HOME</button>
|
||||||
<router-outlet></router-outlet>`,
|
<router-outlet></router-outlet>
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
userName = new FormControl();
|
userName = new FormControl();
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [],
|
imports: [],
|
||||||
template: `<div>Home</div>`,
|
template: `
|
||||||
|
<div>Home</div>
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
export default class HomeComponent {}
|
export default class HomeComponent {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { AsyncPipe, NgFor } from '@angular/common';
|
|||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
inject,
|
|
||||||
OnInit,
|
OnInit,
|
||||||
|
inject,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { loadActivities } from './store/activity/activity.actions';
|
import { loadActivities } from './store/activity/activity.actions';
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
import { ApplicationConfig } from '@angular/core';
|
||||||
import { provideStore } from '@ngrx/store';
|
|
||||||
import { provideEffects } from '@ngrx/effects';
|
import { provideEffects } from '@ngrx/effects';
|
||||||
|
import { provideStore } from '@ngrx/store';
|
||||||
import { ActivityEffects } from './store/activity/activity.effects';
|
import { ActivityEffects } from './store/activity/activity.effects';
|
||||||
import { UserEffects } from './store/user/user.effects';
|
|
||||||
import { StatusEffects } from './store/status/status.effects';
|
|
||||||
import {
|
import {
|
||||||
activityFeatureKey,
|
activityFeatureKey,
|
||||||
activityReducer,
|
activityReducer,
|
||||||
} from './store/activity/activity.reducer';
|
} from './store/activity/activity.reducer';
|
||||||
|
import { StatusEffects } from './store/status/status.effects';
|
||||||
|
import { UserEffects } from './store/user/user.effects';
|
||||||
|
|
||||||
import { statusFeatureKey, statusReducer } from './store/status/status.reducer';
|
import { statusFeatureKey, statusReducer } from './store/status/status.reducer';
|
||||||
|
|
||||||
|
|||||||
@@ -13,18 +13,18 @@ export class ActivityEffects {
|
|||||||
concatMap(() =>
|
concatMap(() =>
|
||||||
this.ActivityService.fetchActivities().pipe(
|
this.ActivityService.fetchActivities().pipe(
|
||||||
map((activities) =>
|
map((activities) =>
|
||||||
ActivityActions.loadActivitiesSuccess({ activities })
|
ActivityActions.loadActivitiesSuccess({ activities }),
|
||||||
),
|
),
|
||||||
catchError((error) =>
|
catchError((error) =>
|
||||||
of(ActivityActions.loadActivitiesFailure({ error }))
|
of(ActivityActions.loadActivitiesFailure({ error })),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private actions$: Actions,
|
private actions$: Actions,
|
||||||
private ActivityService: ActivityService
|
private ActivityService: ActivityService,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ export const activityReducer = createReducer(
|
|||||||
on(ActivityActions.loadActivitiesFailure, (state) => ({
|
on(ActivityActions.loadActivitiesFailure, (state) => ({
|
||||||
state,
|
state,
|
||||||
activities: [],
|
activities: [],
|
||||||
}))
|
})),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
import { activityFeatureKey, ActivityState } from './activity.reducer';
|
import { ActivityState, activityFeatureKey } from './activity.reducer';
|
||||||
|
|
||||||
export const selectActivityState =
|
export const selectActivityState =
|
||||||
createFeatureSelector<ActivityState>(activityFeatureKey);
|
createFeatureSelector<ActivityState>(activityFeatureKey);
|
||||||
|
|
||||||
export const selectActivities = createSelector(
|
export const selectActivities = createSelector(
|
||||||
selectActivityState,
|
selectActivityState,
|
||||||
(state) => state.activities
|
(state) => state.activities,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ export const loadStatuses = createAction('[Status] Load Statuses');
|
|||||||
|
|
||||||
export const loadStatusesSuccess = createAction(
|
export const loadStatusesSuccess = createAction(
|
||||||
'[Status] Load Statuses Success',
|
'[Status] Load Statuses Success',
|
||||||
props<{ statuses: Status[] }>()
|
props<{ statuses: Status[] }>(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class StatusEffects {
|
|||||||
return activities.reduce(
|
return activities.reduce(
|
||||||
(status: Status[], activity): Status[] => {
|
(status: Status[], activity): Status[] => {
|
||||||
const index = status.findIndex(
|
const index = status.findIndex(
|
||||||
(s) => s.name === activity.type
|
(s) => s.name === activity.type,
|
||||||
);
|
);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
return [
|
return [
|
||||||
@@ -34,16 +34,19 @@ export class StatusEffects {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}),
|
}),
|
||||||
map((statuses) => StatusActions.loadStatusesSuccess({ statuses }))
|
map((statuses) => StatusActions.loadStatusesSuccess({ statuses })),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions, private store: Store) {}
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
private store: Store,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ export const statusReducer = createReducer(
|
|||||||
statuses,
|
statuses,
|
||||||
teachersMap: map,
|
teachersMap: map,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
import { ActivityType } from '../activity/activity.model';
|
import { ActivityType } from '../activity/activity.model';
|
||||||
import { statusFeatureKey, StatusState } from './status.reducer';
|
import { StatusState, statusFeatureKey } from './status.reducer';
|
||||||
|
|
||||||
export const selectStatusState =
|
export const selectStatusState =
|
||||||
createFeatureSelector<StatusState>(statusFeatureKey);
|
createFeatureSelector<StatusState>(statusFeatureKey);
|
||||||
|
|
||||||
export const selectStatuses = createSelector(
|
export const selectStatuses = createSelector(
|
||||||
selectStatusState,
|
selectStatusState,
|
||||||
(state) => state.statuses
|
(state) => state.statuses,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectAllTeachersByActivityType = (name: ActivityType) =>
|
export const selectAllTeachersByActivityType = (name: ActivityType) =>
|
||||||
createSelector(
|
createSelector(
|
||||||
selectStatusState,
|
selectStatusState,
|
||||||
(state) => state.teachersMap.get(name) ?? []
|
(state) => state.teachersMap.get(name) ?? [],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,11 +13,14 @@ export class UserEffects {
|
|||||||
concatMap(() =>
|
concatMap(() =>
|
||||||
this.userService.fetchUser().pipe(
|
this.userService.fetchUser().pipe(
|
||||||
map((user) => UserActions.loadUsersSuccess({ user })),
|
map((user) => UserActions.loadUsersSuccess({ user })),
|
||||||
catchError((error) => of(UserActions.loadUsersFailure({ error })))
|
catchError((error) => of(UserActions.loadUsersFailure({ error }))),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions, private userService: UserService) {}
|
constructor(
|
||||||
|
private actions$: Actions,
|
||||||
|
private userService: UserService,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ export const initialState: UserState = {
|
|||||||
export const userReducer = createReducer(
|
export const userReducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
on(UserActions.loadUsersSuccess, (state, { user }) => ({ ...state, user })),
|
on(UserActions.loadUsersSuccess, (state, { user }) => ({ ...state, user })),
|
||||||
on(UserActions.loadUsersFailure, (state) => ({ ...state, user: undefined }))
|
on(UserActions.loadUsersFailure, (state) => ({ ...state, user: undefined })),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
import { userFeatureKey, UserState } from './user.reducer';
|
import { UserState, userFeatureKey } from './user.reducer';
|
||||||
|
|
||||||
export const selectUserState = createFeatureSelector<UserState>(userFeatureKey);
|
export const selectUserState = createFeatureSelector<UserState>(userFeatureKey);
|
||||||
|
|
||||||
export const selectUser = createSelector(
|
export const selectUser = createSelector(
|
||||||
selectUserState,
|
selectUserState,
|
||||||
(state) => state.user
|
(state) => state.user,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
|
||||||
import { provideStore } from '@ngrx/store';
|
|
||||||
import { provideEffects } from '@ngrx/effects';
|
|
||||||
import { TeacherEffects } from './teacher/store/teacher.effects';
|
|
||||||
import { StudentEffects } from './student/store/student.effects';
|
|
||||||
import { provideRouter } from '@angular/router';
|
|
||||||
import { ROUTES } from './routes';
|
|
||||||
import { APP_INITIALIZER, inject } from '@angular/core';
|
|
||||||
import { FakeBackendService } from '@angular-challenges/ngrx-notification/backend';
|
import { FakeBackendService } from '@angular-challenges/ngrx-notification/backend';
|
||||||
|
import { APP_INITIALIZER, ApplicationConfig, inject } from '@angular/core';
|
||||||
|
import { provideRouter } from '@angular/router';
|
||||||
|
import { provideEffects } from '@ngrx/effects';
|
||||||
|
import { provideStore } from '@ngrx/store';
|
||||||
import { NotificationService } from './data-access/notification.service';
|
import { NotificationService } from './data-access/notification.service';
|
||||||
import {
|
import { ROUTES } from './routes';
|
||||||
teacherReducer,
|
import { StudentEffects } from './student/store/student.effects';
|
||||||
teachersFeatureKey,
|
|
||||||
} from './teacher/store/teacher.reducer';
|
|
||||||
import {
|
import {
|
||||||
studentReducer,
|
studentReducer,
|
||||||
studentsFeatureKey,
|
studentsFeatureKey,
|
||||||
} from './student/store/student.reducer';
|
} from './student/store/student.reducer';
|
||||||
|
import { TeacherEffects } from './teacher/store/teacher.effects';
|
||||||
|
import {
|
||||||
|
teacherReducer,
|
||||||
|
teachersFeatureKey,
|
||||||
|
} from './teacher/store/teacher.reducer';
|
||||||
|
|
||||||
const REDUCERS = {
|
const REDUCERS = {
|
||||||
[teachersFeatureKey]: teacherReducer,
|
[teachersFeatureKey]: teacherReducer,
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export class NotificationService {
|
|||||||
.subscribe((notification: Push) => {
|
.subscribe((notification: Push) => {
|
||||||
if (isTeacher(notification)) {
|
if (isTeacher(notification)) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
teacherActions.addOneTeacher({ teacher: notification })
|
teacherActions.addOneTeacher({ teacher: notification }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isStudent(notification)) {
|
if (isStudent(notification)) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
studentActions.addOneStudent({ student: notification })
|
studentActions.addOneStudent({ student: notification }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isSchool(notification)) {
|
if (isSchool(notification)) {
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ export class SchoolStore
|
|||||||
this.httpService.getAllSchools().pipe(
|
this.httpService.getAllSchools().pipe(
|
||||||
tapResponse(
|
tapResponse(
|
||||||
(schools) => this.patchState({ schools }),
|
(schools) => this.patchState({ schools }),
|
||||||
(_) => _
|
(_) => _,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
ngrxOnStoreInit() {
|
ngrxOnStoreInit() {
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export class StudentEffects {
|
|||||||
switchMap(() =>
|
switchMap(() =>
|
||||||
this.httpService
|
this.httpService
|
||||||
.getAllStudents()
|
.getAllStudents()
|
||||||
.pipe(map((students) => studentActions.addAllStudents({ students })))
|
.pipe(map((students) => studentActions.addAllStudents({ students }))),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ export const studentAdapter: EntityAdapter<Student> =
|
|||||||
export const studentReducer = createReducer(
|
export const studentReducer = createReducer(
|
||||||
studentAdapter.getInitialState(),
|
studentAdapter.getInitialState(),
|
||||||
on(studentActions.addOneStudent, (state, { student }) =>
|
on(studentActions.addOneStudent, (state, { student }) =>
|
||||||
studentAdapter.upsertOne(student, state)
|
studentAdapter.upsertOne(student, state),
|
||||||
),
|
),
|
||||||
on(studentActions.addAllStudents, (state, { students }) =>
|
on(studentActions.addAllStudents, (state, { students }) =>
|
||||||
studentAdapter.setAll(students, state)
|
studentAdapter.setAll(students, state),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const { selectIds, selectEntities, selectAll, selectTotal } =
|
export const { selectIds, selectEntities, selectAll, selectTotal } =
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
import {
|
import {
|
||||||
|
StudentState,
|
||||||
studentAdapter,
|
studentAdapter,
|
||||||
studentsFeatureKey,
|
studentsFeatureKey,
|
||||||
StudentState,
|
|
||||||
} from './student.reducer';
|
} from './student.reducer';
|
||||||
|
|
||||||
const selectStudentState =
|
const selectStudentState =
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export class TeacherEffects {
|
|||||||
switchMap(() =>
|
switchMap(() =>
|
||||||
this.httpService
|
this.httpService
|
||||||
.getAllTeachers()
|
.getAllTeachers()
|
||||||
.pipe(map((teachers) => teacherActions.addAllTeachers({ teachers })))
|
.pipe(map((teachers) => teacherActions.addAllTeachers({ teachers }))),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ export const teacherAdapter: EntityAdapter<Teacher> =
|
|||||||
export const teacherReducer = createReducer(
|
export const teacherReducer = createReducer(
|
||||||
teacherAdapter.getInitialState(),
|
teacherAdapter.getInitialState(),
|
||||||
on(teacherActions.addOneTeacher, (state, { teacher }) =>
|
on(teacherActions.addOneTeacher, (state, { teacher }) =>
|
||||||
teacherAdapter.upsertOne(teacher, state)
|
teacherAdapter.upsertOne(teacher, state),
|
||||||
),
|
),
|
||||||
on(teacherActions.addAllTeachers, (state, { teachers }) =>
|
on(teacherActions.addAllTeachers, (state, { teachers }) =>
|
||||||
teacherAdapter.setAll(teachers, state)
|
teacherAdapter.setAll(teachers, state),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const { selectIds, selectEntities, selectAll, selectTotal } =
|
export const { selectIds, selectEntities, selectAll, selectTotal } =
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||||
import {
|
import {
|
||||||
|
TeacherState,
|
||||||
teacherAdapter,
|
teacherAdapter,
|
||||||
teachersFeatureKey,
|
teachersFeatureKey,
|
||||||
TeacherState,
|
|
||||||
} from './teacher.reducer';
|
} from './teacher.reducer';
|
||||||
|
|
||||||
const selectTeacherState =
|
const selectTeacherState =
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ import { bootstrapApplication } from '@angular/platform-browser';
|
|||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -147,7 +147,9 @@ body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
left: 40px;
|
left: 40px;
|
||||||
box-shadow: 38px 0 #0078ca, 19px 20px #f69697;
|
box-shadow:
|
||||||
|
38px 0 #0078ca,
|
||||||
|
19px 20px #f69697;
|
||||||
}
|
}
|
||||||
.eyes:before {
|
.eyes:before {
|
||||||
height: 12px;
|
height: 12px;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { MatListModule } from '@angular/material/list';
|
|||||||
CDFlashingDirective,
|
CDFlashingDirective,
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
<h1 cd-flash class="font-semibold text-center" title="Title">
|
<h1 cd-flash class="text-center font-semibold" title="Title">
|
||||||
{{ title | titlecase }}
|
{{ title | titlecase }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-random',
|
selector: 'app-random',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
template: `<div cd-flash>I do nothing but I'm here</div>`,
|
template: `
|
||||||
|
<div cd-flash>I do nothing but I'm here</div>
|
||||||
|
`,
|
||||||
imports: [CDFlashingDirective],
|
imports: [CDFlashingDirective],
|
||||||
})
|
})
|
||||||
export class RandomComponent {}
|
export class RandomComponent {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { PersonListComponent } from './person-list.component';
|
|||||||
<p>Performance is key!!</p>
|
<p>Performance is key!!</p>
|
||||||
<button
|
<button
|
||||||
(click)="loadList = true"
|
(click)="loadList = true"
|
||||||
class="border border-black p-2 rounded-md">
|
class="rounded-md border border-black p-2">
|
||||||
Load List
|
Load List
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const fibonacci = (num: number): number => {
|
|||||||
MatChipsModule,
|
MatChipsModule,
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
<h1 class="font-semibold text-center" title="Title">
|
<h1 class="text-center font-semibold" title="Title">
|
||||||
{{ title | titlecase }}
|
{{ title | titlecase }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ const fibonacci = (num: number): number => {
|
|||||||
<mat-list-item *ngFor="let person of persons">
|
<mat-list-item *ngFor="let person of persons">
|
||||||
<div MatListItemLine class="flex justify-between">
|
<div MatListItemLine class="flex justify-between">
|
||||||
<h3>{{ person.name }}</h3>
|
<h3>{{ person.name }}</h3>
|
||||||
<mat-chip> {{ calculate(person.fib) }} </mat-chip>
|
<mat-chip>{{ calculate(person.fib) }}</mat-chip>
|
||||||
</div>
|
</div>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
</mat-list>
|
</mat-list>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ import { PersonListComponent } from './person-list.component';
|
|||||||
template: `
|
template: `
|
||||||
<button
|
<button
|
||||||
(click)="loadList.set(true)"
|
(click)="loadList.set(true)"
|
||||||
class="border border-black p-2 rounded-md">
|
class="rounded-md border border-black p-2">
|
||||||
Load List
|
Load List
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<app-person-list
|
<app-person-list
|
||||||
*ngIf="loadList()"
|
*ngIf="loadList()"
|
||||||
class="max-w-2xl w-3/4"
|
class="w-3/4 max-w-2xl"
|
||||||
[persons]="persons()" />
|
[persons]="persons()" />
|
||||||
`,
|
`,
|
||||||
host: {
|
host: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class PersonService {
|
|||||||
this.persons.set(
|
this.persons.set(
|
||||||
this.fakeBackend
|
this.fakeBackend
|
||||||
.returnNewList(this.persons())
|
.returnNewList(this.persons())
|
||||||
.filter((p) => p.email !== email)
|
.filter((p) => p.email !== email),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ export class PersonService {
|
|||||||
this.persons.set(
|
this.persons.set(
|
||||||
this.fakeBackend
|
this.fakeBackend
|
||||||
.returnNewList(this.persons())
|
.returnNewList(this.persons())
|
||||||
.map((p) => (p.email === email ? { email, name: randFirstName() } : p))
|
.map((p) => (p.email === email ? { email, name: randFirstName() } : p)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import { Person } from './person.model';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, NgForTrackByModule],
|
imports: [CommonModule, NgForTrackByModule],
|
||||||
template: `
|
template: `
|
||||||
<div class="h-[300px] relative overflow-hidden">
|
<div class="relative h-[300px] overflow-hidden">
|
||||||
<div class="absolute inset-0 overflow-scroll">
|
<div class="absolute inset-0 overflow-scroll">
|
||||||
<div
|
<div
|
||||||
*ngFor="let person of persons; trackByProp: 'email'"
|
*ngFor="let person of persons; trackByProp: 'email'"
|
||||||
class="flex justify-between items-center border-b h-9">
|
class="flex h-9 items-center justify-between border-b">
|
||||||
<h3>{{ person.name }}</h3>
|
<h3>{{ person.name }}</h3>
|
||||||
<p>{{ person.email }}</p>
|
<p>{{ person.email }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
console.error(err)
|
console.error(err),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { PersonListComponent } from './person-list.component';
|
|||||||
providers: [PersonService],
|
providers: [PersonService],
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
template: `
|
template: `
|
||||||
<h1 class="font-semibold text-center text-3xl" title="Title">
|
<h1 class="text-center text-3xl font-semibold" title="Title">
|
||||||
List of Persons
|
List of Persons
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ import { PersonListComponent } from './person-list.component';
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<app-person-list
|
<app-person-list
|
||||||
class="max-w-2xl w-3/4"
|
class="w-3/4 max-w-2xl"
|
||||||
[persons]="persons()"
|
[persons]="persons()"
|
||||||
(delete)="personService.deletePerson($event)"
|
(delete)="personService.deletePerson($event)"
|
||||||
(update)="personService.updatePerson($event)" />
|
(update)="personService.updatePerson($event)" />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class PersonService {
|
|||||||
this.persons.set(
|
this.persons.set(
|
||||||
this.fakeBackend
|
this.fakeBackend
|
||||||
.returnNewList(this.persons())
|
.returnNewList(this.persons())
|
||||||
.filter((p) => p.email !== email)
|
.filter((p) => p.email !== email),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ export class PersonService {
|
|||||||
this.persons.set(
|
this.persons.set(
|
||||||
this.fakeBackend
|
this.fakeBackend
|
||||||
.returnNewList(this.persons())
|
.returnNewList(this.persons())
|
||||||
.map((p) => (p.email === email ? { email, name: randFirstName() } : p))
|
.map((p) => (p.email === email ? { email, name: randFirstName() } : p)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ import { Person } from './person.model';
|
|||||||
template: `
|
template: `
|
||||||
<div
|
<div
|
||||||
*ngFor="let person of persons"
|
*ngFor="let person of persons"
|
||||||
class="flex justify-between items-center border-b">
|
class="flex items-center justify-between border-b">
|
||||||
<h3>{{ person.name }}</h3>
|
<h3>{{ person.name }}</h3>
|
||||||
<div class="flex gap-10 py-1">
|
<div class="flex gap-10 py-1">
|
||||||
<button
|
<button
|
||||||
class="border rounded-md p-2 bg-blue-500 text-white"
|
class="rounded-md border bg-blue-500 p-2 text-white"
|
||||||
(click)="update.emit(person.email)">
|
(click)="update.emit(person.email)">
|
||||||
UPDATE
|
UPDATE
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="border rounded-md p-2 bg-red-500 text-white"
|
class="rounded-md border bg-red-500 p-2 text-white"
|
||||||
(click)="delete.emit(person.email)">
|
(click)="delete.emit(person.email)">
|
||||||
DELETE
|
DELETE
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user