Skip to content

Commit 1811327

Browse files
committed
add use-cases for project, skills, subs, invites, kanban & chat
1 parent aee6007 commit 1811327

135 files changed

Lines changed: 2762 additions & 565 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { catchError, map, Observable, of } from "rxjs";
5+
import { AuthRepositoryPort } from "../../../domain/auth/ports/auth.repository.port";
6+
import { fail, ok, Result } from "../../../domain/shared/result.type";
7+
8+
@Injectable({ providedIn: "root" })
9+
export class DownloadCvUseCase {
10+
private readonly authRepositoryPort = inject(AuthRepositoryPort);
11+
12+
execute(): Observable<Result<Blob, { kind: "download_cv_error"; cause?: unknown }>> {
13+
return this.authRepositoryPort.downloadCV().pipe(
14+
map(file => ok<Blob>(file)),
15+
catchError(error => of(fail({ kind: "download_cv_error" as const, cause: error })))
16+
);
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { catchError, map, Observable, of } from "rxjs";
5+
import { fail, ok, Result } from "../../../domain/shared/result.type";
6+
import { ChatRepositoryPort } from "../../../domain/chat/ports/chat.repository.port";
7+
8+
export type CheckUnreadsError = { kind: "server_error" };
9+
10+
@Injectable({ providedIn: "root" })
11+
export class CheckUnreadsUseCase {
12+
private readonly chatRepository = inject(ChatRepositoryPort);
13+
14+
execute(): Observable<Result<boolean, CheckUnreadsError>> {
15+
return this.chatRepository.hasUnreads().pipe(
16+
map(hasUnreads => ok<boolean>(hasUnreads)),
17+
catchError(() => of(fail<CheckUnreadsError>({ kind: "server_error" })))
18+
);
19+
}
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { ChatRealtimePort } from "../../../domain/chat/ports/chat-realtime.port";
5+
import { DeleteChatMessageDto } from "../../../domain/chat/chat.model";
6+
7+
@Injectable({ providedIn: "root" })
8+
export class DeleteMessageUseCase {
9+
private readonly chatRealtime = inject(ChatRealtimePort);
10+
11+
execute(message: DeleteChatMessageDto): void {
12+
this.chatRealtime.deleteMessage(message);
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { ChatRealtimePort } from "../../../domain/chat/ports/chat-realtime.port";
5+
import { EditChatMessageDto } from "../../../domain/chat/chat.model";
6+
7+
@Injectable({ providedIn: "root" })
8+
export class EditMessageUseCase {
9+
private readonly chatRealtime = inject(ChatRealtimePort);
10+
11+
execute(message: EditChatMessageDto): void {
12+
this.chatRealtime.editMessage(message);
13+
}
14+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { catchError, map, Observable, of } from "rxjs";
5+
import { fail, ok, Result } from "../../../domain/shared/result.type";
6+
import { ChatRepositoryPort } from "../../../domain/chat/ports/chat.repository.port";
7+
import { ApiPagination } from "../../../domain/other/api-pagination.model";
8+
import { ChatMessage } from "../../../domain/chat/chat-message.model";
9+
10+
export type LoadMessagesError = { kind: "server_error" };
11+
12+
@Injectable({ providedIn: "root" })
13+
export class LoadMessagesUseCase {
14+
private readonly chatRepository = inject(ChatRepositoryPort);
15+
16+
execute(
17+
projectId: number,
18+
offset?: number,
19+
limit?: number
20+
): Observable<Result<ApiPagination<ChatMessage>, LoadMessagesError>> {
21+
return this.chatRepository.loadMessages(projectId, offset, limit).pipe(
22+
map(page => ok<ApiPagination<ChatMessage>>(page)),
23+
catchError(() => of(fail<LoadMessagesError>({ kind: "server_error" })))
24+
);
25+
}
26+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { catchError, map, Observable, of } from "rxjs";
5+
import { fail, ok, Result } from "../../../domain/shared/result.type";
6+
import { ChatRepositoryPort } from "../../../domain/chat/ports/chat.repository.port";
7+
import { ChatFile } from "../../../domain/chat/chat-message.model";
8+
9+
export type LoadProjectFilesError = { kind: "server_error" };
10+
11+
@Injectable({ providedIn: "root" })
12+
export class LoadProjectFilesUseCase {
13+
private readonly chatRepository = inject(ChatRepositoryPort);
14+
15+
execute(projectId: number): Observable<Result<ChatFile[], LoadProjectFilesError>> {
16+
return this.chatRepository.loadProjectFiles(projectId).pipe(
17+
map(files => ok<ChatFile[]>(files)),
18+
catchError(() => of(fail<LoadProjectFilesError>({ kind: "server_error" })))
19+
);
20+
}
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { ChatRealtimePort } from "../../../domain/chat/ports/chat-realtime.port";
5+
import { ReadChatMessageDto } from "../../../domain/chat/chat.model";
6+
7+
@Injectable({ providedIn: "root" })
8+
export class ReadMessageUseCase {
9+
private readonly chatRealtime = inject(ChatRealtimePort);
10+
11+
execute(message: ReadChatMessageDto): void {
12+
this.chatRealtime.readMessage(message);
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @format */
2+
3+
import { inject, Injectable } from "@angular/core";
4+
import { ChatRealtimePort } from "../../../domain/chat/ports/chat-realtime.port";
5+
import { SendChatMessageDto } from "../../../domain/chat/chat.model";
6+
7+
@Injectable({ providedIn: "root" })
8+
export class SendMessageUseCase {
9+
private readonly chatRealtime = inject(ChatRealtimePort);
10+
11+
execute(message: SendChatMessageDto): void {
12+
this.chatRealtime.sendMessage(message);
13+
}
14+
}

projects/social_platform/src/app/api/feed/facades/feed-info.service.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ import {
1515
throttleTime,
1616
} from "rxjs";
1717
import { FeedItem, FeedItemType } from "../../../domain/feed/feed-item.model";
18-
import { ApiPagination } from "projects/skills/src/models/api-pagination.model";
18+
import { ApiPagination } from "../../../domain/other/api-pagination.model";
1919
import { FeedUIInfoService } from "./ui/feed-ui-info.service";
20-
import { FeedHttpAdapter } from "../../../infrastructure/adapters/feed/feed-http.adapter";
21-
import { ProjectNewsRepository } from "../../../infrastructure/repository/project/project-news.repository";
22-
import { ProfileNewsRepository } from "../../../infrastructure/repository/profile/profile-news.repository";
20+
import { FetchFeedUseCase } from "../use-cases/fetch-feed.use-case";
21+
import { ReadFeedNewsUseCase } from "../use-cases/read-feed-news.use-case";
22+
import { ToggleFeedLikeUseCase } from "../use-cases/toggle-feed-like.use-case";
2323

2424
const DEFAULT_FEED_TYPES: FeedItemType[] = ["vacancy", "project", "news"];
2525
const FILTER_SPLIT_SYMBOL = "|";
2626

2727
@Injectable()
2828
export class FeedInfoService {
2929
private readonly route = inject(ActivatedRoute);
30-
private readonly projectNewsRepository = inject(ProjectNewsRepository);
31-
private readonly profileNewsRepository = inject(ProfileNewsRepository);
32-
private readonly feedHttpAdapter = inject(FeedHttpAdapter);
30+
private readonly fetchFeedUseCase = inject(FetchFeedUseCase);
31+
private readonly readFeedNewsUseCase = inject(ReadFeedNewsUseCase);
32+
private readonly toggleFeedLikeUseCase = inject(ToggleFeedLikeUseCase);
3333
private readonly feedUIInfoService = inject(FeedUIInfoService);
3434

3535
private observer?: IntersectionObserver;
@@ -147,11 +147,11 @@ export class FeedInfoService {
147147
? DEFAULT_FEED_TYPES.join(FILTER_SPLIT_SYMBOL)
148148
: includes.join(FILTER_SPLIT_SYMBOL);
149149

150-
return this.feedHttpAdapter.fetchFeed(offset, limit, type).pipe(
151-
tap(res => {
152-
this.feedUIInfoService.totalItemsCount.set(res.count);
150+
return this.fetchFeedUseCase.execute(offset, limit, type).pipe(
151+
tap(result => {
152+
this.feedUIInfoService.totalItemsCount.set(result.ok ? result.value.count : 0);
153153
}),
154-
map(res => res.results)
154+
map(result => (result.ok ? result.value.results : []))
155155
);
156156
}
157157

@@ -172,16 +172,16 @@ export class FeedInfoService {
172172

173173
projectNews.forEach(news => {
174174
if (news.typeModel !== "news") return;
175-
this.projectNewsRepository
176-
.readNews(news.content.contentObject.id, [news.content.id])
175+
this.readFeedNewsUseCase
176+
.execute("project", news.content.contentObject.id, [news.content.id])
177177
.pipe(takeUntil(this.destroy$))
178178
.subscribe();
179179
});
180180

181181
profileNews.forEach(news => {
182182
if (news.typeModel !== "news") return;
183-
this.projectNewsRepository
184-
.readNews(news.content.contentObject.id, [news.content.id])
183+
this.readFeedNewsUseCase
184+
.execute("profile", news.content.contentObject.id, [news.content.id])
185185
.pipe(takeUntil(this.destroy$))
186186
.subscribe();
187187
});
@@ -194,25 +194,31 @@ export class FeedInfoService {
194194
if (!item || item.typeModel !== "news") return;
195195

196196
if ("email" in item.content.contentObject) {
197-
this.profileNewsRepository
198-
.toggleLike(
197+
this.toggleFeedLikeUseCase
198+
.execute(
199+
"profile",
199200
item.content.contentObject.id as unknown as string,
200201
newsId,
201202
!item.content.isUserLiked
202203
)
203204
.pipe(takeUntil(this.destroy$))
204-
.subscribe(() => {
205+
.subscribe(result => {
206+
if (!result.ok) return;
207+
205208
this.feedUIInfoService.applyLikeNews(itemIdx);
206209
});
207210
} else if ("leader" in item.content.contentObject) {
208-
this.projectNewsRepository
209-
.toggleLike(
211+
this.toggleFeedLikeUseCase
212+
.execute(
213+
"project",
210214
item.content.contentObject.id as unknown as string,
211215
newsId,
212216
!item.content.isUserLiked
213217
)
214218
.pipe(takeUntil(this.destroy$))
215-
.subscribe(() => {
219+
.subscribe(result => {
220+
if (!result.ok) return;
221+
216222
this.feedUIInfoService.applyLikeNews(itemIdx);
217223
});
218224
}

projects/social_platform/src/app/api/feed/facades/ui/feed-ui-info.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @format */
22

33
import { Injectable, signal } from "@angular/core";
4-
import { ApiPagination } from "projects/skills/src/models/api-pagination.model";
4+
import { ApiPagination } from "projects/social_platform/src/app/domain/other/api-pagination.model";
55
import { FeedItem } from "projects/social_platform/src/app/domain/feed/feed-item.model";
66

77
@Injectable()

0 commit comments

Comments
 (0)