### Description
This PR updates the application to handle posts that may not have a publication date (e.g., drafts) by making the `published_time` field optional across the entire post feature stack.
This ensures that draft posts can be processed and rendered without causing errors, and prevents search engine metadata from being generated for content that is not yet published.
#### Key Changes:
* **DTO & Schema (`postInfoResponseDto.ts`):**
* The Zod schema for `PostInfoResponseSchema` has been updated to mark `published_time` as `.nullable()`.
* The `PostInfoResponseDto` class now correctly handles a `null` value from the API, mapping it to `Date | null`.
* **Domain Entity (`postInfo.ts`):**
* The core `PostInfo` entity's `publishedTime` property is now typed as `Date | null` to reflect the business logic that a post may be unpublished.
* **View Model (`postInfoViewModel.ts`):**
* Updated `publishedTime` to be `Date | null`.
* Added a new `isPublished` boolean getter for convenient conditional logic in the UI.
* The `formattedPublishedTime` getter now returns `string | null`.
* Dehydration and rehydration logic (`dehydrate`/`rehydrate`) has been updated to correctly handle the nullable `publishedTime`.
* **UI Component (`PostContentPage.svelte`):**
* The component now uses the new `isPublished` flag to conditionally render the `<StructuredData>` component for SEO. This ensures that structured data is only included for posts that have been officially published.
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#118
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #121
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
This pull request introduces the core functionality for creating and updating posts, completing the backend CRUD operations for the `post` feature. It includes new API endpoints, database schema changes, and corresponding updates across the entire application stack from the database layer to the frontend.
#### Backend API
- **Added new authenticated endpoints:**
- `POST /post`: To create a new post.
- `PUT /post/{id}`: To update an existing post.
- Implemented the full vertical slice for these operations, including:
- `CreatePostUseCase` and `UpdatePostUseCase`.
- Repository and DB service methods for creating, updating, and associating posts with labels.
- Transactional database operations to ensure data integrity when creating/updating posts and their associated labels.
#### Database
- Added a new migration to include an `"order"` column in the `post_label` table.
- This column preserves the user-defined order of labels for each post.
- Queries have been updated to fetch and sort labels based on this new column.
#### API Schema & Documentation
- Enhanced `utoipa` OpenAPI documentation with more specific formats for data types:
- `#[schema(format = Uri)]` for URLs like `preview_image_url`.
- `#[schema(format = Email)]` for user emails.
- `#[schema(format = DateTime)]` for timestamps.
- Standardized the `published_time` field to use the RFC3339 string format instead of a numeric timestamp, improving API clarity and interoperability.
#### Frontend
- Updated the `PostInfoResponseDto` in the frontend to correctly parse the new `DateTime` (ISO string) format for `published_time`.
#### Refactoring
- Renamed `get_full_post` to a more descriptive `get_post_by_id` across the post feature module for better code clarity.
### Package Changes
```toml
utoipa = { version = "5.4.0", features = [
"actix_extras",
"non_strict_integers",
"url",
] }
```
### Screenshots
_No response_
### Reference
Resolves#104
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #108
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- Change the format of color response
```json
{
"red": 0,
"green": 255,
"blue": 128,
"alpha": 255
}
```
- The relationship between the label's background color and its highlight color is calculated. The method involves first converting the RGB color value to HSL, then decreasing the L (lightness) component, and finally converting it back to RGB.
### Package Changes
```json
{
"zod": "^4.0.5"
}
```
### Screenshots
|Desktop|Mobile|
|-|-|
|||
### Reference
Resolves#44
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #64
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>