Skip to content

Commit f37b36c

Browse files
ngrx signal store fixes
1 parent 0186a45 commit f37b36c

File tree

10 files changed

+103
-62
lines changed

10 files changed

+103
-62
lines changed

src/app/admin/_components/add-post/add-post.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
import { AdminApiService } from '../../_services/admin-api.service';
2222
import { HighlightModule } from 'ngx-highlightjs';
2323
import { QuillEditorComponent, Range } from 'ngx-quill';
24-
import { Post } from '../../../shared/_models/post.interface';
2524
import { PostForm } from '../../_models/post-from.inteface';
2625
import hljs from 'highlight.js';
2726
import { RouterModule } from '@angular/router';
@@ -30,6 +29,7 @@ import { DynamicDialogService } from '../../../shared/dynamic-dialog/dynamic-dia
3029
import { ModalConfig } from '../../../shared/_models/modal-config.intreface';
3130
import { AddImageComponent } from './add-image/add-image.component';
3231
import { AddImageForm } from './add-image/add-image-controls.interface';
32+
<<<<<<< HEAD
3333
=======
3434
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
3535
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
@@ -38,6 +38,9 @@ import { Firestore, FirestoreModule} from '@angular/fire/firestore';
3838
import { HttpClient } from '@angular/common/http';
3939
import { AsyncPipe } from '@angular/common';
4040
>>>>>>> ab739b9 (nothing special)
41+
=======
42+
import { Post } from '../../../types/supabase';
43+
>>>>>>> fca8c97 (ngrx signal store fixes)
4144

4245
@Component({
4346
selector: 'blog-add-post',

src/app/admin/_services/admin-api.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Injectable, inject } from '@angular/core';
2-
import { Post } from '../../shared/_models/post.interface';
2+
33
import { Observable } from 'rxjs';
4+
import { Post } from '../../supabase-types';
45

56
@Injectable()
67
export class AdminApiService {

src/app/reader/_components/main-page/post/post.component.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import {
1313
} from '@angular/core';
1414
import { ReaderApiService } from '../../../_services/reader-api.service';
1515
import { AsyncPipe, DatePipe } from '@angular/common';
16-
import { Post } from '../../../../shared/_models/post.interface';
17-
import { Observable, from, map } from 'rxjs';
16+
import { Observable, from, map, of } from 'rxjs';
1817
import { CommentsComponent } from './comments/comments.component';
1918
import { AddCommentComponent } from './add-comment/add-comment.component';
2019
import { toSignal } from '@angular/core/rxjs-interop';
@@ -23,7 +22,6 @@ import { Router } from '@angular/router';
2322
import { DomSanitizer } from '@angular/platform-browser';
2423
import { DynamicDialogService } from '../../../../shared/dynamic-dialog/dynamic-dialog.service';
2524
import { CodeBlockModalComponent } from './code-block-modal-component/code-block-modal-component.component';
26-
import { ModalStatus } from '../../../../shared/_models/modal-status.interface';
2725

2826
@Component({
2927
selector: 'app-post',
@@ -47,26 +45,12 @@ export class PostComponent implements OnInit, AfterViewInit {
4745
private sanitizer = inject(DomSanitizer);
4846
private viewContainerRef = inject(ViewContainerRef);
4947

50-
post$!: Observable<Post | null>;
48+
post$!: Observable<any | null>;
5149
comments$!: Signal<Comment[] | undefined>;
5250
date: string = '';
5351

5452
ngOnInit() {
55-
this.post$ = from(this.apiService.getPost(this.id)).pipe(
56-
map((post: Post | null) => {
57-
if (post) {
58-
post.dateJS = post.date.toDate();
59-
this.date = this.datePipe.transform(
60-
post.dateJS,
61-
'dd-MM-yyyy',
62-
) as string;
63-
post.content = this.sanitizer.bypassSecurityTrustHtml(
64-
post.content as string,
65-
);
66-
}
67-
return post;
68-
}),
69-
);
53+
this.post$ = of(null);
7054
this.comments$! = runInInjectionContext(this.injector, () =>
7155
toSignal(this.apiService.getComments(this.id)),
7256
);
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import {Component, Input} from '@angular/core';
2-
import {NgStyle} from "@angular/common";
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import { NgStyle } from '@angular/common';
33

44
@Component({
55
selector: 'app-label',
66
standalone: true,
7-
imports: [
8-
NgStyle
9-
],
7+
imports: [NgStyle],
108
templateUrl: './label.component.html',
11-
styleUrl: './label.component.scss'
9+
styleUrl: './label.component.scss',
1210
})
1311
export class LabelComponent {
1412
@Input() text: string = 'Label';
15-
@Input() position: number = 0; // Position to control vertical spacing
1613
@Input() color: string = '#000000';
1714
}

src/app/reader/_components/main-page/posts-list/post-card/post-card.component.html

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
<div class="bg-white w-full flex flex-col md:flex-row md:pr-4">
88
<div
99
class="flex flex-wrap md:flex-col items-start md:basis-2/12 gap-2 px-4 md:px-0">
10-
@for (tag of tags; track tag.name; let i = $index) {
11-
<app-label
12-
[text]="tag.name"
13-
[position]="i"
14-
[color]="tag.color"
15-
></app-label>
10+
@for (tag of post().post_tags; track tag.tags.id; let i = $index) {
11+
@if (i < 4) {
12+
<app-label
13+
[text]="tag.tags.name"
14+
[color]="tag.tags.color"
15+
></app-label>
16+
}
1617
}
1718
</div>
1819

@@ -21,7 +22,7 @@ <h2 class="font-bold line-clamp-3 text-xl mt-0 text-center leading-relaxed">
2122
{{ post().title }}
2223
</h2>
2324
<div class="line-clamp-3 xl:line-clamp-4 2xl:line-clamp-5 pt-3 leading-loose">
24-
{{ description() }}
25+
{{ post().description }}
2526
</div>
2627
</div>
2728
</div>
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Component, computed, input } from '@angular/core';
2-
import { Post } from '../../../../../shared/_models/post.interface';
32
import { LabelComponent } from '../label/label.component';
4-
import { TAGS } from '../../../../../utlis/tags';
53
import { RouterLink } from '@angular/router';
4+
import { Post } from '../../../../../supabase-types';
65

76
@Component({
87
selector: 'app-post-card',
@@ -12,11 +11,5 @@ import { RouterLink } from '@angular/router';
1211
styleUrl: './post-card.component.scss',
1312
})
1413
export class PostCardComponent {
15-
tagsMock = ['HTML', 'CSS', 'TypeScript', 'SSG/SSR'];
16-
tags = TAGS.filter((tag) => this.tagsMock.includes(tag.name));
17-
1814
post = input.required<Post>();
19-
description = computed(() => {
20-
return this.post().description;
21-
});
2215
}

src/app/reader/_components/main-page/posts-list/posts-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
<div class="flex justify-center mt-5">
8383
<div class="w-full">
8484
<div class="grid">
85-
@for (post of posts$ | async; track post.id; let f = $first) {
85+
@for (post of posts(); track post.id; let f = $first) {
8686
<app-post-card [post]="post"></app-post-card>
8787
}
8888
</div>

src/app/reader/_components/main-page/posts-list/posts-list.component.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import {
2-
AsyncPipe,
3-
DatePipe,
4-
NgOptimizedImage,
5-
NgStyle,
6-
} from '@angular/common';
1+
import { DatePipe, NgOptimizedImage, NgStyle } from '@angular/common';
72
import {
83
CUSTOM_ELEMENTS_SCHEMA,
94
ChangeDetectionStrategy,
@@ -14,27 +9,25 @@ import {
149
ElementRef,
1510
signal,
1611
WritableSignal,
12+
OnInit,
1713
} from '@angular/core';
1814
import { RouterModule } from '@angular/router';
19-
import { map, Observable, of } from 'rxjs';
20-
import { Post } from '../../../../shared/_models/post.interface';
21-
import { ReaderApiService } from '../../../_services/reader-api.service';
2215
import { AboutMeComponent } from '../../../../shared/about-me/about-me.component';
2316
import { PostCardComponent } from './post-card/post-card.component';
2417
import { TAGS } from '../../../../utlis/tags';
18+
import { PostsStore } from './posts.store';
2519

2620
@Component({
2721
selector: 'app-posts-list',
2822
standalone: true,
2923
imports: [
30-
AsyncPipe,
3124
RouterModule,
3225
AboutMeComponent,
3326
PostCardComponent,
3427
NgOptimizedImage,
3528
NgStyle,
3629
],
37-
providers: [ReaderApiService, DatePipe],
30+
providers: [DatePipe],
3831
templateUrl: './posts-list.component.html',
3932
styleUrl: './posts-list.component.scss',
4033
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -43,8 +36,8 @@ import { TAGS } from '../../../../utlis/tags';
4336
export class PostsListComponent {
4437
scroll = viewChild<ElementRef<HTMLElement>>('scrollContainer');
4538
scrollProgress: WritableSignal<number> = signal(0);
46-
apiService = inject(ReaderApiService);
47-
dataPipe = inject(DatePipe);
39+
postStore = inject(PostsStore);
40+
posts = this.postStore.posts;
4841

4942
initialScroll = 2;
5043

@@ -70,6 +63,5 @@ export class PostsListComponent {
7063
this.scrollProgress.set(scrollPercentage);
7164
}
7265

73-
posts$: Observable<Post[]> = of([]);
7466
protected readonly TAGS = TAGS;
7567
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Post } from '../../../../types/supabase';
2+
import {
3+
patchState,
4+
signalStore,
5+
withComputed,
6+
withHooks,
7+
withMethods,
8+
withState,
9+
} from '@ngrx/signals';
10+
import { computed, inject } from '@angular/core';
11+
import { ReaderApiService } from '../../../_services/reader-api.service';
12+
13+
type PostsState = {
14+
posts: Post[];
15+
loading: boolean;
16+
error: string | null;
17+
};
18+
19+
const initialState: PostsState = {
20+
posts: [],
21+
loading: false,
22+
error: null,
23+
};
24+
25+
export const PostsStore = signalStore(
26+
{ providedIn: 'root' },
27+
withState(initialState),
28+
29+
withMethods((state, postService = inject(ReaderApiService)) => ({
30+
async getPosts() {
31+
patchState(state, { loading: true, error: null });
32+
try {
33+
const posts = await postService.getPosts();
34+
if (posts) {
35+
patchState(state, { posts, loading: false });
36+
} else {
37+
patchState(state, { error: 'No posts found', loading: false });
38+
}
39+
} catch (error) {
40+
patchState(state, { error: 'Failed to fetch posts', loading: false });
41+
}
42+
},
43+
})),
44+
withHooks({
45+
onInit(store) {
46+
store.getPosts();
47+
},
48+
}),
49+
);
Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { Injectable } from '@angular/core';
2-
import { Observable, of } from 'rxjs';
3-
import { Post } from '../../shared/_models/post.interface';
1+
import { inject, Injectable } from '@angular/core';
2+
import { Observable } from 'rxjs';
43
import { Comment } from '../../shared/_models/comment.inteface';
4+
import { SupabaseService } from '../../services/supabase.service';
5+
import { Post } from '../../types/supabase';
56

6-
@Injectable()
7+
@Injectable({ providedIn: 'root' })
78
export class ReaderApiService {
9+
supabaseService = inject(SupabaseService);
10+
811
async getPost(id: string): Promise<Post | null> {
912
return null;
1013
}
@@ -16,4 +19,22 @@ export class ReaderApiService {
1619
addComment(postId: string, comment: Comment): void {}
1720

1821
deleteComment(commentId: string, postId: string): void {}
22+
23+
async getPosts(): Promise<Post[] | null> {
24+
const { data: posts } = await this.supabaseService.getClient
25+
.from('posts')
26+
.select(
27+
`
28+
*,
29+
author:profiles ( id, username, avatar_url ),
30+
post_tags (
31+
tags ( id, name, color, icon )
32+
)
33+
`,
34+
)
35+
.eq('is_draft', false)
36+
.order('created_at', { ascending: false });
37+
38+
return posts;
39+
}
1940
}

0 commit comments

Comments
 (0)