Skip to content

Commit 0e9770c

Browse files
changed to rest api
1 parent abb5351 commit 0e9770c

File tree

10 files changed

+151
-99
lines changed

10 files changed

+151
-99
lines changed

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@angular/platform-server": "^19.2.1",
2424
"@angular/router": "^19.2.1",
2525
"@angular/ssr": "^19.2.1",
26+
"@ngrx/operators": "^19.1.0",
2627
"@ngrx/signals": "^19.1.0",
2728
"@supabase/supabase-js": "^2.49.4",
2829
"@tailwindcss/line-clamp": "^0.4.4",
Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { Post } from '../../../../types/supabase';
2-
import {
3-
patchState,
4-
signalStore,
5-
withHooks,
6-
withMethods,
7-
withState,
8-
} from '@ngrx/signals';
91
import { inject } from '@angular/core';
2+
import { patchState, signalStore, withMethods, withState } from '@ngrx/signals';
3+
import { rxMethod } from '@ngrx/signals/rxjs-interop';
4+
import { pipe, switchMap, tap } from 'rxjs';
5+
import { tapResponse } from '@ngrx/operators';
6+
7+
import { Post } from '../../../../types/supabase';
108
import { ReaderApiService } from '../../../_services/reader-api.service';
119

1210
type PostState = {
@@ -25,19 +23,23 @@ export const PostStore = signalStore(
2523
{ providedIn: 'root' },
2624
withState(initialState),
2725

28-
withMethods((state, postService = inject(ReaderApiService)) => ({
29-
async getPost(id: string) {
30-
patchState(state, { loading: true, error: null });
31-
try {
32-
const post = await postService.getPost(id);
33-
if (post) {
34-
patchState(state, { post, loading: false });
35-
} else {
36-
patchState(state, { error: 'Post not found', loading: false });
37-
}
38-
} catch (error) {
39-
patchState(state, { error: 'Failed to fetch post', loading: false });
40-
}
41-
},
26+
withMethods((store, postService = inject(ReaderApiService)) => ({
27+
getPost: rxMethod<string>(
28+
pipe(
29+
tap(() => patchState(store, { loading: true, error: null })),
30+
switchMap((id) =>
31+
postService.getPost(id).pipe(
32+
tapResponse({
33+
next: (post: Post) => patchState(store, { post, loading: false }),
34+
error: (err: string) =>
35+
patchState(store, {
36+
error: err ?? 'Failed to fetch post',
37+
loading: false,
38+
}),
39+
}),
40+
),
41+
),
42+
),
43+
),
4244
})),
4345
);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ export class PostsListComponent implements OnInit {
5252
this.initializeScrollingForMobileView();
5353
}
5454

55-
async ngOnInit() {}
55+
ngOnInit() {
56+
console.log(this.posts());
57+
}
5658

5759
onScroll(event: Event) {
5860
const target = event.target as HTMLElement;
Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
import { Post } from '../../../../types/supabase';
1+
import { computed, inject } from '@angular/core';
2+
import { tapResponse } from '@ngrx/operators';
23
import {
34
patchState,
45
signalStore,
5-
withComputed,
6-
withHooks,
7-
withMethods,
86
withState,
7+
withMethods,
8+
withHooks,
9+
withComputed,
910
} from '@ngrx/signals';
10-
import { computed, inject } from '@angular/core';
11+
import { rxMethod } from '@ngrx/signals/rxjs-interop';
12+
import { pipe, switchMap, tap } from 'rxjs';
13+
14+
import { Post } from '../../../../types/supabase';
1115
import { ReaderApiService } from '../../../_services/reader-api.service';
1216

1317
type PostsState = {
14-
posts: Post[];
18+
posts: Post[] | null;
1519
loading: boolean;
1620
error: string | null;
1721
};
@@ -25,25 +29,33 @@ const initialState: PostsState = {
2529
export const PostsStore = signalStore(
2630
{ providedIn: 'root' },
2731
withState(initialState),
32+
withMethods((store, api = inject(ReaderApiService)) => ({
33+
loadPosts: rxMethod<void>(
34+
pipe(
35+
tap(() => patchState(store, { loading: true, error: null })),
36+
switchMap(() =>
37+
api.getPosts().pipe(
38+
tapResponse({
39+
next: (posts) => patchState(store, { posts, loading: false }),
40+
error: (err) =>
41+
patchState(store, {
42+
error: 'Failed to fetch posts',
43+
loading: false,
44+
}),
45+
}),
46+
),
47+
),
48+
),
49+
),
50+
})),
2851

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-
}
52+
withHooks(({ loadPosts }) => ({
53+
onInit() {
54+
loadPosts();
4255
},
4356
})),
44-
withHooks({
45-
onInit(store) {
46-
store.getPosts();
47-
},
48-
}),
57+
58+
withComputed(({ posts }) => ({
59+
total: computed(() => posts()!.length),
60+
})),
4961
);

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

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,41 @@
11
import { inject, Injectable } from '@angular/core';
22
import { SupabaseService } from '../../services/supabase.service';
33
import { Comment, Post, Profile, Tag, PostTag } from '../../types/supabase';
4+
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
5+
import { map, Observable } from 'rxjs';
46

57
@Injectable({ providedIn: 'root' })
68
export class ReaderApiService {
79
supabaseService = inject(SupabaseService);
10+
http = inject(HttpClient);
11+
private readonly baseUrl =
12+
'https://aqdbdmepncxxuanlymwr.supabase.co/rest/v1/posts';
13+
private readonly apiKey =
14+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFxZGJkbWVwbmN4eHVhbmx5bXdyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDUwNTA0MjYsImV4cCI6MjA2MDYyNjQyNn0.RNtZZ4Of4LIP3XuS9lumHYdjRLVUGXARtAxaTJmF7lc';
815

9-
async getPost(id: string): Promise<any | null> {
10-
const { data, error } = await this.supabaseService.getClient
11-
.from('posts')
12-
.select(
13-
`
16+
getPost(id: string): Observable<Post> {
17+
const selectQuery = `
1418
*,
15-
author:profiles ( id, username, avatar_url ),
16-
tags:post_tags!inner (
17-
tags ( id, name, color, icon )
18-
),
19-
comments:comments (
20-
id, content, created_at, is_deleted, is_reported,
21-
author:profiles ( id, username, avatar_url )
22-
)
23-
`,
24-
)
25-
.eq('id', id)
26-
.single();
27-
28-
return error ? null : data;
19+
author:profiles(id,username,avatar_url),
20+
post_tags!inner(tags(id,name,color,icon)),
21+
comments(id,content,created_at,is_deleted,is_reported,author:profiles(id,username,avatar_url))
22+
`
23+
.replace(/\s+/g, ' ')
24+
.trim();
25+
26+
const params = new HttpParams()
27+
.set('select', selectQuery)
28+
.set('id', `eq.${id}`);
29+
30+
const headers = new HttpHeaders({
31+
apikey: this.apiKey,
32+
Authorization: `Bearer ${this.apiKey}`,
33+
Accept: 'application/json',
34+
});
35+
36+
return this.http
37+
.get<Post[]>(this.baseUrl, { headers, params })
38+
.pipe(map((results) => results[0] ?? null));
2939
}
3040

3141
async getComments(postId: string): Promise<Comment[]> {
@@ -51,24 +61,47 @@ export class ReaderApiService {
5161
.eq('post_id', postId);
5262
}
5363

54-
async getPosts(): Promise<Post[] | null> {
55-
const { data: posts } = await this.supabaseService.getClient
56-
.from('posts')
57-
.select(
58-
`
59-
*,
60-
author:profiles ( id, username, avatar_url ),
61-
post_tags (
62-
tags ( id, name, color, icon )
63-
)
64-
`,
65-
)
66-
.eq('is_draft', false)
67-
.order('created_at', { ascending: false });
68-
69-
return posts;
64+
getPosts(): Observable<Post[] | null> {
65+
const selectQuery = `
66+
*,
67+
author:profiles(id,username,avatar_url),
68+
post_tags(tags(id,name,color,icon))
69+
`
70+
.replace(/\s+/g, ' ')
71+
.trim();
72+
73+
const params = new HttpParams()
74+
.set('select', selectQuery)
75+
.set('is_draft', 'eq.false')
76+
.set('order', 'created_at.desc');
77+
78+
const headers = new HttpHeaders({
79+
apikey: this.apiKey,
80+
Authorization: `Bearer ${this.apiKey}`,
81+
Accept: 'application/json',
82+
});
83+
84+
return this.http.get<Post[]>(this.baseUrl, { headers, params });
7085
}
7186

87+
// async getPosts(): Promise<Post[] | null> {
88+
// const { data: posts } = await this.supabaseService.getClient
89+
// .from('posts')
90+
// .select(
91+
// `
92+
// *,
93+
// author:profiles ( id, username, avatar_url ),
94+
// post_tags (
95+
// tags ( id, name, color, icon )
96+
// )
97+
// `,
98+
// )
99+
// .eq('is_draft', false)
100+
// .order('created_at', { ascending: false });
101+
//
102+
// return posts;
103+
// }
104+
72105
async getProfiles(): Promise<Profile[] | null> {
73106
const { data: profiles, error } = await this.supabaseService.getClient
74107
.from('profiles')
Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1 @@
1-
import { PostsStore } from './_components/main-page/posts-list/posts.store';
2-
import { inject, PLATFORM_ID } from '@angular/core';
3-
import { isPlatformServer } from '@angular/common';
4-
5-
export const postListResolver = async () => {
6-
const platformId = inject(PLATFORM_ID);
7-
if (!isPlatformServer(platformId)) {
8-
return true;
9-
}
10-
const postStore = inject(PostsStore);
11-
await postStore.getPosts();
12-
return true;
13-
};
1+
export const postListResolver = () => {};

src/app/reader/reader.routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const readerRoutes: Routes = [
1313
{
1414
path: '',
1515
component: PostsListComponent,
16-
resolve: [postListResolver, tagListResolver],
16+
// resolve: [postListResolver, tagListResolver],
1717
},
1818
{
1919
path: 'details/:id',
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export const environment = {
22
production: false,
3-
supabaseUrl: '',
4-
supabaseKey: '',
3+
supabaseUrl: 'https://aqdbdmepncxxuanlymwr.supabase.co',
4+
supabaseKey:
5+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFxZGJkbWVwbmN4eHVhbmx5bXdyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDUwNTA0MjYsImV4cCI6MjA2MDYyNjQyNn0.RNtZZ4Of4LIP3XuS9lumHYdjRLVUGXARtAxaTJmF7lc',
56
};

src/environments/environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export const environment = {
2-
production: false,
2+
production: true,
33
supabaseUrl: 'https://aqdbdmepncxxuanlymwr.supabase.co',
44
supabaseKey:
55
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFxZGJkbWVwbmN4eHVhbmx5bXdyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDUwNTA0MjYsImV4cCI6MjA2MDYyNjQyNn0.RNtZZ4Of4LIP3XuS9lumHYdjRLVUGXARtAxaTJmF7lc',

0 commit comments

Comments
 (0)