Compare commits
No commits in common. "898ee86f91cbda3ee289d6f9fb6eba4c87f0bf45" and "9862850d283f2ac74b2000eef447f01f9687e12c" have entirely different histories.
898ee86f91
...
9862850d28
@ -1 +0,0 @@
|
|||||||
PUBLIC_API_BASE_URL=http://127.0.0.1:5173/api/
|
|
@ -3,5 +3,5 @@ import type { PostResponseDto } from '$lib/post/adapter/gateway/postResponseDto'
|
|||||||
|
|
||||||
export interface PostApiService {
|
export interface PostApiService {
|
||||||
getAllPosts(): Promise<PostInfoResponseDto[]>;
|
getAllPosts(): Promise<PostInfoResponseDto[]>;
|
||||||
getPost(id: string): Promise<PostResponseDto | null>;
|
getPost(id: number): Promise<PostResponseDto | null>;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import z from 'zod';
|
|||||||
|
|
||||||
export const PostInfoResponseSchema = z.object({
|
export const PostInfoResponseSchema = z.object({
|
||||||
id: z.int32(),
|
id: z.int32(),
|
||||||
semantic_id: z.string(),
|
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
preview_image_url: z.url(),
|
preview_image_url: z.url(),
|
||||||
@ -14,7 +13,6 @@ export const PostInfoResponseSchema = z.object({
|
|||||||
|
|
||||||
export class PostInfoResponseDto {
|
export class PostInfoResponseDto {
|
||||||
readonly id: number;
|
readonly id: number;
|
||||||
readonly semanticId: string;
|
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly description: string;
|
readonly description: string;
|
||||||
readonly previewImageUrl: URL;
|
readonly previewImageUrl: URL;
|
||||||
@ -23,7 +21,6 @@ export class PostInfoResponseDto {
|
|||||||
|
|
||||||
private constructor(props: {
|
private constructor(props: {
|
||||||
id: number;
|
id: number;
|
||||||
semanticId: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
previewImageUrl: URL;
|
previewImageUrl: URL;
|
||||||
@ -31,7 +28,6 @@ export class PostInfoResponseDto {
|
|||||||
publishedTime: Date | null;
|
publishedTime: Date | null;
|
||||||
}) {
|
}) {
|
||||||
this.id = props.id;
|
this.id = props.id;
|
||||||
this.semanticId = props.semanticId;
|
|
||||||
this.title = props.title;
|
this.title = props.title;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.previewImageUrl = props.previewImageUrl;
|
this.previewImageUrl = props.previewImageUrl;
|
||||||
@ -49,7 +45,6 @@ export class PostInfoResponseDto {
|
|||||||
|
|
||||||
return new PostInfoResponseDto({
|
return new PostInfoResponseDto({
|
||||||
id: parsedJson.id,
|
id: parsedJson.id,
|
||||||
semanticId: parsedJson.semantic_id,
|
|
||||||
title: parsedJson.title,
|
title: parsedJson.title,
|
||||||
description: parsedJson.description,
|
description: parsedJson.description,
|
||||||
previewImageUrl: new URL(parsedJson.preview_image_url),
|
previewImageUrl: new URL(parsedJson.preview_image_url),
|
||||||
@ -61,7 +56,6 @@ export class PostInfoResponseDto {
|
|||||||
toEntity(): PostInfo {
|
toEntity(): PostInfo {
|
||||||
return new PostInfo({
|
return new PostInfo({
|
||||||
id: this.id,
|
id: this.id,
|
||||||
semanticId: this.semanticId,
|
|
||||||
title: this.title,
|
title: this.title,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
previewImageUrl: this.previewImageUrl,
|
previewImageUrl: this.previewImageUrl,
|
||||||
|
@ -11,7 +11,7 @@ export class PostRepositoryImpl implements PostRepository {
|
|||||||
return dtos.map((dto) => dto.toEntity());
|
return dtos.map((dto) => dto.toEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPost(id: string): Promise<Post | null> {
|
async getPost(id: number): Promise<Post | null> {
|
||||||
const dto = await this.postApiService.getPost(id);
|
const dto = await this.postApiService.getPost(id);
|
||||||
return dto?.toEntity() ?? null;
|
return dto?.toEntity() ?? null;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ export class PostBloc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadPost(id: string): Promise<PostState> {
|
private async loadPost(id: number): Promise<PostState> {
|
||||||
this.state.set({ status: StatusType.Loading, data: get(this.state).data });
|
this.state.set({ status: StatusType.Loading, data: get(this.state).data });
|
||||||
|
|
||||||
const post = await this.getPostUseCase.execute(id);
|
const post = await this.getPostUseCase.execute(id);
|
||||||
@ -56,7 +56,7 @@ export enum PostEventType {
|
|||||||
PostLoadedEvent
|
PostLoadedEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PostLoadedEvent {
|
export interface PostLoadedEvent {
|
||||||
event: PostEventType.PostLoadedEvent;
|
event: PostEventType.PostLoadedEvent;
|
||||||
id: string;
|
id: number;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import type { PostInfo } from '$lib/post/domain/entity/postInfo';
|
|||||||
|
|
||||||
export class PostInfoViewModel {
|
export class PostInfoViewModel {
|
||||||
readonly id: number;
|
readonly id: number;
|
||||||
readonly semanticId: string;
|
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly description: string;
|
readonly description: string;
|
||||||
readonly previewImageUrl: URL;
|
readonly previewImageUrl: URL;
|
||||||
@ -15,7 +14,6 @@ export class PostInfoViewModel {
|
|||||||
|
|
||||||
private constructor(props: {
|
private constructor(props: {
|
||||||
id: number;
|
id: number;
|
||||||
semanticId: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
previewImageUrl: URL;
|
previewImageUrl: URL;
|
||||||
@ -23,7 +21,6 @@ export class PostInfoViewModel {
|
|||||||
publishedTime: Date | null;
|
publishedTime: Date | null;
|
||||||
}) {
|
}) {
|
||||||
this.id = props.id;
|
this.id = props.id;
|
||||||
this.semanticId = props.semanticId;
|
|
||||||
this.title = props.title;
|
this.title = props.title;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.previewImageUrl = props.previewImageUrl;
|
this.previewImageUrl = props.previewImageUrl;
|
||||||
@ -34,7 +31,6 @@ export class PostInfoViewModel {
|
|||||||
static fromEntity(postInfo: PostInfo): PostInfoViewModel {
|
static fromEntity(postInfo: PostInfo): PostInfoViewModel {
|
||||||
return new PostInfoViewModel({
|
return new PostInfoViewModel({
|
||||||
id: postInfo.id,
|
id: postInfo.id,
|
||||||
semanticId: postInfo.semanticId,
|
|
||||||
title: postInfo.title,
|
title: postInfo.title,
|
||||||
description: postInfo.description,
|
description: postInfo.description,
|
||||||
previewImageUrl: postInfo.previewImageUrl,
|
previewImageUrl: postInfo.previewImageUrl,
|
||||||
@ -51,7 +47,6 @@ export class PostInfoViewModel {
|
|||||||
|
|
||||||
return new PostInfoViewModel({
|
return new PostInfoViewModel({
|
||||||
id: props.id,
|
id: props.id,
|
||||||
semanticId: props.semanticId,
|
|
||||||
title: props.title,
|
title: props.title,
|
||||||
description: props.description,
|
description: props.description,
|
||||||
previewImageUrl: new URL(props.previewImageUrl),
|
previewImageUrl: new URL(props.previewImageUrl),
|
||||||
@ -71,7 +66,6 @@ export class PostInfoViewModel {
|
|||||||
dehydrate(): DehydratedPostInfoProps {
|
dehydrate(): DehydratedPostInfoProps {
|
||||||
return {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
semanticId: this.semanticId,
|
|
||||||
title: this.title,
|
title: this.title,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
previewImageUrl: this.previewImageUrl.href,
|
previewImageUrl: this.previewImageUrl.href,
|
||||||
@ -83,7 +77,6 @@ export class PostInfoViewModel {
|
|||||||
|
|
||||||
export interface DehydratedPostInfoProps {
|
export interface DehydratedPostInfoProps {
|
||||||
id: number;
|
id: number;
|
||||||
semanticId: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
previewImageUrl: string;
|
previewImageUrl: string;
|
||||||
|
@ -3,5 +3,5 @@ import type { PostInfo } from '$lib/post/domain/entity/postInfo';
|
|||||||
|
|
||||||
export interface PostRepository {
|
export interface PostRepository {
|
||||||
getAllPosts(): Promise<PostInfo[]>;
|
getAllPosts(): Promise<PostInfo[]>;
|
||||||
getPost(id: string): Promise<Post | null>;
|
getPost(id: number): Promise<Post | null>;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import type { Post } from '$lib/post/domain/entity/post';
|
|||||||
export class GetPostUseCase {
|
export class GetPostUseCase {
|
||||||
constructor(private readonly postRepository: PostRepository) {}
|
constructor(private readonly postRepository: PostRepository) {}
|
||||||
|
|
||||||
execute(id: string): Promise<Post | null> {
|
execute(id: number): Promise<Post | null> {
|
||||||
return this.postRepository.getPost(id);
|
return this.postRepository.getPost(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import type { Label } from '$lib/post/domain/entity/label';
|
|||||||
|
|
||||||
export class PostInfo {
|
export class PostInfo {
|
||||||
readonly id: number;
|
readonly id: number;
|
||||||
readonly semanticId: string;
|
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly description: string;
|
readonly description: string;
|
||||||
readonly previewImageUrl: URL;
|
readonly previewImageUrl: URL;
|
||||||
@ -11,7 +10,6 @@ export class PostInfo {
|
|||||||
|
|
||||||
constructor(props: {
|
constructor(props: {
|
||||||
id: number;
|
id: number;
|
||||||
semanticId: string;
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
previewImageUrl: URL;
|
previewImageUrl: URL;
|
||||||
@ -19,7 +17,6 @@ export class PostInfo {
|
|||||||
publishedTime: Date | null;
|
publishedTime: Date | null;
|
||||||
}) {
|
}) {
|
||||||
this.id = props.id;
|
this.id = props.id;
|
||||||
this.semanticId = props.semanticId;
|
|
||||||
this.title = props.title;
|
this.title = props.title;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.previewImageUrl = props.previewImageUrl;
|
this.previewImageUrl = props.previewImageUrl;
|
||||||
|
@ -19,7 +19,7 @@ export class PostApiServiceImpl implements PostApiService {
|
|||||||
return json.map(PostInfoResponseDto.fromJson);
|
return json.map(PostInfoResponseDto.fromJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPost(id: string): Promise<PostResponseDto | null> {
|
async getPost(id: number): Promise<PostResponseDto | null> {
|
||||||
const url = new URL(`post/${id}`, Environment.API_BASE_URL);
|
const url = new URL(`post/${id}`, Environment.API_BASE_URL);
|
||||||
|
|
||||||
const response = await this.fetchFn(url.href);
|
const response = await this.fetchFn(url.href);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import generateTitle from '$lib/common/framework/ui/generateTitle';
|
import generateTitle from '$lib/common/framework/ui/generateTitle';
|
||||||
import StructuredData from '$lib/post/framework/ui/StructuredData.svelte';
|
import StructuredData from '$lib/post/framework/ui/StructuredData.svelte';
|
||||||
|
|
||||||
const { id }: { id: string } = $props();
|
const { id }: { id: number } = $props();
|
||||||
|
|
||||||
const postBloc = getContext<PostBloc>(PostBloc.name);
|
const postBloc = getContext<PostBloc>(PostBloc.name);
|
||||||
const state = $derived($postBloc);
|
const state = $derived($postBloc);
|
||||||
@ -32,7 +32,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<article class="prose prose-gray container pb-10">
|
<article class="container prose pb-10 prose-gray">
|
||||||
{#if state.data}
|
{#if state.data}
|
||||||
<PostContentHeader postInfo={state.data.info} />
|
<PostContentHeader postInfo={state.data.info} />
|
||||||
<div class="max-w-3xl">
|
<div class="max-w-3xl">
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a class="flex cursor-pointer flex-col gap-y-6" href="/post/{postInfo.semanticId}" title={postInfo.title}>
|
<a class="flex cursor-pointer flex-col gap-y-6" href="/post/{postInfo.id}" title={postInfo.title}>
|
||||||
<div class="relative aspect-video overflow-hidden rounded-2xl bg-gray-200">
|
<div class="relative aspect-video overflow-hidden rounded-2xl bg-gray-200">
|
||||||
<img
|
<img
|
||||||
class="rounded-2xl object-cover transition-opacity duration-300
|
class="rounded-2xl object-cover transition-opacity duration-300
|
||||||
|
@ -5,9 +5,14 @@ import type { PageServerLoad } from './$types';
|
|||||||
export const load: PageServerLoad = async ({ locals, params }) => {
|
export const load: PageServerLoad = async ({ locals, params }) => {
|
||||||
const { postBloc } = locals;
|
const { postBloc } = locals;
|
||||||
|
|
||||||
|
const id = parseInt(params.id, 10);
|
||||||
|
if (isNaN(id) || id <= 0) {
|
||||||
|
error(400, { message: 'Invalid post ID' });
|
||||||
|
}
|
||||||
|
|
||||||
const state = await postBloc.dispatch({
|
const state = await postBloc.dispatch({
|
||||||
event: PostEventType.PostLoadedEvent,
|
event: PostEventType.PostLoadedEvent,
|
||||||
id: params.id
|
id: id
|
||||||
});
|
});
|
||||||
if (!state.data) {
|
if (!state.data) {
|
||||||
error(404, { message: 'Post not found' });
|
error(404, { message: 'Post not found' });
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
import PostContentPage from '$lib/post/framework/ui/PostContentPage.svelte';
|
import PostContentPage from '$lib/post/framework/ui/PostContentPage.svelte';
|
||||||
|
|
||||||
const { data, params }: PageProps = $props();
|
const { data, params }: PageProps = $props();
|
||||||
const { id } = params;
|
|
||||||
|
const id = parseInt(params.id, 10);
|
||||||
|
|
||||||
const initialData = PostViewModel.rehydrate(data.dehydratedData!);
|
const initialData = PostViewModel.rehydrate(data.dehydratedData!);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user