initial commit
This commit is contained in:
17
internal/dto/account.go
Normal file
17
internal/dto/account.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// UserInfoResponse is a flat response with user and profile_id.
|
||||
type UserInfoResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
Status string `json:"status"`
|
||||
ProfileID *uuid.UUID `json:"profile_id,omitempty"`
|
||||
}
|
||||
138
internal/dto/asset.go
Normal file
138
internal/dto/asset.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"base/pkg/validation"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CreateAssetRequest struct {
|
||||
ProfileID string `json:"profile_id"`
|
||||
AssetCategoryID string `json:"asset_category_id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
|
||||
func (*CreateAssetRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"profile_id": validation.Rule{Field: "profile_id", Type: validation.ValidationTypeString, Required: true},
|
||||
"asset_category_id": validation.Rule{Field: "asset_category_id", Type: validation.ValidationTypeString, Required: true},
|
||||
"title": validation.Rule{Field: "title", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type UpdateAssetRequest struct {
|
||||
ID string `uri:"id"`
|
||||
AssetCategoryID string `json:"asset_category_id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Link string `json:"link"`
|
||||
Status *int `json:"status"`
|
||||
}
|
||||
|
||||
func (*UpdateAssetRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type GetAssetRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*GetAssetRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type ListAssetsByProfileRequest struct {
|
||||
ProfileID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*ListAssetsByProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"ProfileID": validation.Rule{Field: "profile_id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteAssetRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*DeleteAssetRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type AssetResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ProfileID uuid.UUID `json:"profile_id"`
|
||||
OwnerID *uuid.UUID `json:"owner_id,omitempty"`
|
||||
AssetCategoryID uuid.UUID `json:"asset_category_id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Link string `json:"link"`
|
||||
CoverImage string `json:"cover_image,omitempty"`
|
||||
Status int `json:"status"`
|
||||
Category CategoryDTO `json:"category"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CategoryDTO struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
Color string `json:"color"`
|
||||
CardType string `json:"card_type"`
|
||||
Featured bool `json:"featured"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type ListAssetsResponse struct {
|
||||
Assets []AssetResponse `json:"assets"`
|
||||
}
|
||||
|
||||
// ListAssetsByCategoryIDResponse is paginated assets for a single category (Phase 2 of two-phase loading).
|
||||
type ListAssetsByCategoryIDResponse struct {
|
||||
Category CategoryDTO `json:"category"`
|
||||
Assets []AssetResponse `json:"assets"`
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
}
|
||||
|
||||
type ListCategoriesResponse struct {
|
||||
Categories []CategoryDTO `json:"categories"`
|
||||
}
|
||||
|
||||
// CategoriesPreviewRequest holds the request body for POST /assets/categories/preview.
|
||||
type CategoriesPreviewRequest struct {
|
||||
CategoryIDs []string `json:"category_ids"`
|
||||
AssetsPerCategory int `json:"assets_per_category"`
|
||||
FeaturedOnly bool `json:"featured_only"`
|
||||
}
|
||||
|
||||
func (*CategoriesPreviewRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"category_ids": validation.Rule{Field: "category_ids", Type: validation.ValidationTypeArray, Required: false},
|
||||
"assets_per_category": validation.Rule{Field: "assets_per_category", Type: validation.ValidationTypeInt, Required: false},
|
||||
"featured_only": validation.Rule{Field: "featured_only", Type: validation.ValidationTypeBool, Required: false},
|
||||
}
|
||||
}
|
||||
|
||||
// CategoryWithPreviewAssetsDTO groups a category with up to N sample assets.
|
||||
type CategoryWithPreviewAssetsDTO struct {
|
||||
Category CategoryDTO `json:"category"`
|
||||
Assets []AssetResponse `json:"assets"`
|
||||
TotalAssets int `json:"total_assets,omitempty"`
|
||||
HasMore bool `json:"has_more,omitempty"`
|
||||
}
|
||||
|
||||
// CategoriesPreviewResponse is the response for POST /assets/categories/preview.
|
||||
type CategoriesPreviewResponse struct {
|
||||
Categories []CategoryWithPreviewAssetsDTO `json:"categories"`
|
||||
}
|
||||
291
internal/dto/auth.go
Normal file
291
internal/dto/auth.go
Normal file
@@ -0,0 +1,291 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
|
||||
"base/internal/pkg/oauth"
|
||||
"base/pkg/validation"
|
||||
)
|
||||
|
||||
type RegisterRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
}
|
||||
|
||||
func (*RegisterRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
"password": validation.Rule{
|
||||
Field: "password",
|
||||
Type: validation.ValidationTypeString,
|
||||
MinLength: validation.IntPtr(8),
|
||||
MaxLength: validation.IntPtr(32),
|
||||
Required: true,
|
||||
},
|
||||
"first_name": validation.Rule{
|
||||
Field: "first_name",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"last_name": validation.Rule{
|
||||
Field: "last_name",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"phone_number": validation.Rule{
|
||||
Field: "phone_number",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type LoginRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (*LoginRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
"password": validation.Rule{
|
||||
Field: "password",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type TokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
func (*TokenResponse) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"access_token": validation.Rule{
|
||||
Field: "access_token",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"refresh_token": validation.Rule{
|
||||
Field: "refresh_token",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type RefreshTokenRequest struct {
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
func (*RefreshTokenRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"refresh_token": validation.Rule{
|
||||
Field: "refresh_token",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type SendVerificationEmailRequest struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func (*SendVerificationEmailRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type SetupProfileRequest struct {
|
||||
Handle string `json:"handle"`
|
||||
RoleID uuid.UUID `json:"role_id"`
|
||||
RoleLevel string `json:"role_level"`
|
||||
ShortDescription string `json:"short_description"`
|
||||
}
|
||||
|
||||
func (*SetupProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"handle": validation.Rule{
|
||||
Field: "handle",
|
||||
Type: validation.ValidationTypeString,
|
||||
MinLength: validation.IntPtr(2),
|
||||
MaxLength: validation.IntPtr(80),
|
||||
Required: true,
|
||||
},
|
||||
"role_id": validation.Rule{
|
||||
Field: "role_id",
|
||||
Type: validation.ValidationTypeUUID,
|
||||
Required: false,
|
||||
},
|
||||
"role_level": validation.Rule{
|
||||
Field: "role_level",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: false,
|
||||
},
|
||||
"short_description": validation.Rule{
|
||||
Field: "short_description",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type VerifyAccountRequest struct {
|
||||
Email string `json:"email"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func (*VerifyAccountRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
"code": validation.Rule{
|
||||
Field: "code",
|
||||
Type: validation.ValidationTypeString,
|
||||
MinLength: validation.IntPtr(6),
|
||||
MaxLength: validation.IntPtr(6),
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type OAuthRedirectURLRequest struct {
|
||||
Provider oauth.Provider `json:"provider"`
|
||||
}
|
||||
|
||||
func (*OAuthRedirectURLRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"provider": validation.Rule{
|
||||
Field: "provider",
|
||||
Path: "provider",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type OAuthRedirectURLResponse struct {
|
||||
RedirectURL string `json:"redirect_url"`
|
||||
}
|
||||
|
||||
func (*OAuthRedirectURLResponse) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"redirect_url": validation.Rule{
|
||||
Field: "redirect_url",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type OAuthCallbackRequest struct {
|
||||
Provider oauth.Provider `json:"provider"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func (*OAuthCallbackRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"provider": validation.Rule{
|
||||
Field: "provider",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"code": validation.Rule{
|
||||
Field: "code",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type OAuthCallbackResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
IsNewUser bool `json:"is_new_user"`
|
||||
}
|
||||
|
||||
func (*OAuthCallbackResponse) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"access_token": validation.Rule{
|
||||
Field: "access_token",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"refresh_token": validation.Rule{
|
||||
Field: "refresh_token",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
"is_new_user": validation.Rule{
|
||||
Field: "is_new_user",
|
||||
Type: validation.ValidationTypeBool,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type SendResetPasswordEmailRequest struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func (*SendResetPasswordEmailRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type ResetPasswordRequest struct {
|
||||
Email string `json:"email"`
|
||||
Code string `json:"code"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (*ResetPasswordRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"email": validation.Rule{
|
||||
Field: "email",
|
||||
Type: validation.ValidationTypeEmail,
|
||||
Required: true,
|
||||
},
|
||||
"code": validation.Rule{
|
||||
Field: "code",
|
||||
Type: validation.ValidationTypeString,
|
||||
MinLength: validation.IntPtr(6),
|
||||
MaxLength: validation.IntPtr(6),
|
||||
Required: true,
|
||||
},
|
||||
"password": validation.Rule{
|
||||
Field: "password",
|
||||
Type: validation.ValidationTypeString,
|
||||
MinLength: validation.IntPtr(8),
|
||||
MaxLength: validation.IntPtr(32),
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
7
internal/dto/base.go
Normal file
7
internal/dto/base.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package dto
|
||||
|
||||
import "base/pkg/validation"
|
||||
|
||||
type DTO interface {
|
||||
Schema() validation.Schema
|
||||
}
|
||||
26
internal/dto/blog.go
Normal file
26
internal/dto/blog.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package dto
|
||||
|
||||
import "time"
|
||||
|
||||
type Blog struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Summary string `json:"summary"`
|
||||
CoverImage string `json:"cover_image"`
|
||||
ContentHtml string `json:"content_html"`
|
||||
ContentJson interface{} `json:"content_json"`
|
||||
Status string `json:"status"`
|
||||
IsFeatured bool `json:"is_featured"`
|
||||
ViewCount int `json:"view_count"`
|
||||
Slug string `json:"slug"`
|
||||
CategoryId string `json:"category_id"`
|
||||
Category struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
} `json:"category"`
|
||||
MetaTags interface{} `json:"meta_tags"`
|
||||
Author string `json:"author"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
92
internal/dto/landing.go
Normal file
92
internal/dto/landing.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package dto
|
||||
|
||||
//type Landing struct {
|
||||
// Message string `json:"message"`
|
||||
// Data struct {
|
||||
// Categories []struct {
|
||||
// Id string `json:"id"`
|
||||
// Title string `json:"title"`
|
||||
// Featured bool `json:"featured"`
|
||||
// Icon string `json:"icon"`
|
||||
// Color string `json:"color"`
|
||||
// CardType string `json:"card_type"`
|
||||
// Order int `json:"order"`
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// UpdatedAt time.Time `json:"updated_at"`
|
||||
// } `json:"categories"`
|
||||
// SpecialistRole []struct {
|
||||
// Id string `json:"id"`
|
||||
// Title string `json:"title"`
|
||||
// Status string `json:"status"`
|
||||
// } `json:"specialist_role"`
|
||||
// Assets []struct {
|
||||
// Id string `json:"id"`
|
||||
// Title string `json:"title"`
|
||||
// Icon string `json:"icon"`
|
||||
// Assets []struct {
|
||||
// Id string `json:"id"`
|
||||
// CoverImage string `json:"cover_image"`
|
||||
// Title string `json:"title"`
|
||||
// Avatar string `json:"avatar"`
|
||||
// Description string `json:"description"`
|
||||
// AuthorName string `json:"author_name"`
|
||||
// Price int `json:"price"`
|
||||
// Currency string `json:"currency"`
|
||||
// CategoryId string `json:"category_id"`
|
||||
// CategoryName string `json:"category_name"`
|
||||
// CardType string `json:"card_type"`
|
||||
// } `json:"assets"`
|
||||
// } `json:"assets"`
|
||||
// Specialists []struct {
|
||||
// Id string `json:"id"`
|
||||
// Handle string `json:"handle"`
|
||||
// Avatar string `json:"avatar"`
|
||||
// } `json:"specialists"`
|
||||
// Blog []struct {
|
||||
// Id string `json:"id"`
|
||||
// Title string `json:"title"`
|
||||
// Content string `json:"content"`
|
||||
// Summary string `json:"summary"`
|
||||
// CoverImage string `json:"cover_image"`
|
||||
// ContentHtml string `json:"content_html"`
|
||||
// ContentJson interface{} `json:"content_json"`
|
||||
// Status string `json:"status"`
|
||||
// IsFeatured bool `json:"is_featured"`
|
||||
// ViewCount int `json:"view_count"`
|
||||
// Slug string `json:"slug"`
|
||||
// CategoryId string `json:"category_id"`
|
||||
// Category struct {
|
||||
// Id string `json:"id"`
|
||||
// Title string `json:"title"`
|
||||
// } `json:"category"`
|
||||
// MetaTags interface{} `json:"meta_tags"`
|
||||
// Author string `json:"author"`
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// UpdatedAt time.Time `json:"updated_at"`
|
||||
// } `json:"blog"`
|
||||
// } `json:"data"`
|
||||
//}
|
||||
|
||||
type Landing struct {
|
||||
Message string `json:"message"`
|
||||
Data LandingPageData `json:"data"`
|
||||
}
|
||||
|
||||
type AssetCategory struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
type LandingAssetData struct {
|
||||
AssetCategory
|
||||
Assets []AssetResponse `json:"assets"`
|
||||
}
|
||||
|
||||
type LandingPageData struct {
|
||||
Categories []CategoryDTO `json:"categories"`
|
||||
SpecialistRoles []ProfileRole `json:"specialist_roles"`
|
||||
Assets []LandingAssetData `json:"assets"`
|
||||
Specialists []Specialist `json:"specialists"`
|
||||
Blogs []Blog `json:"blogs"`
|
||||
}
|
||||
157
internal/dto/overview.go
Normal file
157
internal/dto/overview.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package dto
|
||||
|
||||
import "time"
|
||||
|
||||
// OverviewResponse is the dashboard response for authenticated users with a profile
|
||||
type OverviewResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data OverviewDataDTO `json:"data"`
|
||||
}
|
||||
|
||||
type OverviewDataDTO struct {
|
||||
Analytics AnalyticsDTO `json:"analytics"`
|
||||
RecentlyJoined []FlatProfileDTO `json:"recently_joined"`
|
||||
Assets []AssetResponse `json:"assets"`
|
||||
CompletionPercent int `json:"completionPercent"`
|
||||
Tasks TasksDTO `json:"tasks"`
|
||||
}
|
||||
|
||||
// OverviewFetchedResponse matches "Overview fetched successfully" format (assets with content, cover_image, etc.)
|
||||
type OverviewFetchedResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data OverviewFetchedDataDTO `json:"data"`
|
||||
}
|
||||
|
||||
type OverviewFetchedDataDTO struct {
|
||||
Assets []OverviewAssetDTO `json:"assets"`
|
||||
RecentlyJoined []FlatProfileDTO `json:"recently_joined"`
|
||||
Analytics AnalyticsDTO `json:"analytics"`
|
||||
}
|
||||
|
||||
// SpecialistOverviewFetchedDataDTO extends OverviewFetchedDataDTO with specialist's Profile, Skills, completionPercent, and tasks
|
||||
type SpecialistOverviewFetchedDataDTO struct {
|
||||
Assets []OverviewAssetDTO `json:"assets"`
|
||||
RecentlyJoined []FlatProfileDTO `json:"recently_joined"`
|
||||
Analytics AnalyticsDTO `json:"analytics"`
|
||||
Profile *ProfileResponse `json:"profile,omitempty"`
|
||||
Skills []SkillDTO `json:"skills,omitempty"`
|
||||
CompletionPercent int `json:"completionPercent"`
|
||||
Tasks TasksDTO `json:"tasks"`
|
||||
}
|
||||
|
||||
// SpecialistOverviewFetchedResponse is the specialist overview response (includes Profile + Skills)
|
||||
type SpecialistOverviewFetchedResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data SpecialistOverviewFetchedDataDTO `json:"data"`
|
||||
}
|
||||
|
||||
// OverviewAssetDTO is the full asset format for overview (content, cover_image, price, etc.)
|
||||
type OverviewAssetDTO struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
AssetCategoryID string `json:"asset_category_id"`
|
||||
AssetCategory *CategoryDTO `json:"asset_category"`
|
||||
CoverImage string `json:"cover_image"`
|
||||
Link string `json:"link"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
ProfileID string `json:"profile_id"`
|
||||
Profile interface{} `json:"profile"`
|
||||
Price int `json:"price"`
|
||||
Currency string `json:"currency"`
|
||||
Status string `json:"status"`
|
||||
Rating int `json:"rating"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type AnalyticsDTO struct {
|
||||
TotalAssets int `json:"total_assets"`
|
||||
TotalProfiles int `json:"total_profiles"`
|
||||
}
|
||||
|
||||
// CategoryAssetsDTO groups assets under a category for discovery.
|
||||
type CategoryAssetsDTO struct {
|
||||
Category CategoryDTO `json:"category"`
|
||||
Assets []OverviewAssetDTO `json:"assets"`
|
||||
}
|
||||
|
||||
// CategoryAssetsPaginatedDTO groups paginated assets under a category.
|
||||
type CategoryAssetsPaginatedDTO struct {
|
||||
Category CategoryDTO `json:"category"`
|
||||
Assets []OverviewAssetDTO `json:"assets"`
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
}
|
||||
|
||||
// ListAssetsByCategoryResponse is the paginated API response for assets by category.
|
||||
type ListAssetsByCategoryResponse struct {
|
||||
Data ListAssetsByCategoryResponseData `json:"data"`
|
||||
}
|
||||
|
||||
// ListAssetsByCategoryResponseData holds the categories with paginated assets.
|
||||
type ListAssetsByCategoryResponseData struct {
|
||||
Categories []CategoryAssetsPaginatedDTO `json:"categories"`
|
||||
}
|
||||
|
||||
// AssetsByCategoryResponse is the API response for assets grouped by category (at least 6 per category).
|
||||
type AssetsByCategoryResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data AssetsByCategoryResponseData `json:"data"`
|
||||
}
|
||||
|
||||
type AssetsByCategoryResponseData struct {
|
||||
Categories map[string]CategoryAssetsDTO `json:"categories"`
|
||||
}
|
||||
|
||||
type TasksDTO struct {
|
||||
ProfileAction bool `json:"profile_action"`
|
||||
AboutAction bool `json:"about_action"`
|
||||
PublishAction bool `json:"publish_action"`
|
||||
WorksAction bool `json:"works_action"`
|
||||
SkillsAction bool `json:"skills_action"`
|
||||
SocialAction bool `json:"social_action"`
|
||||
}
|
||||
|
||||
// FlatProfileDTO is the flat profile format for recently_joined and similar lists
|
||||
type FlatProfileDTO struct {
|
||||
ID string `json:"id"`
|
||||
ProfileHandle string `json:"profile_handle"`
|
||||
Status string `json:"status"`
|
||||
BackgroundImage string `json:"background_image"`
|
||||
ProfilePicture string `json:"profile_picture"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
RoleID string `json:"role_id"`
|
||||
Role RoleDTO `json:"role"`
|
||||
CurrentCompany string `json:"current_company"`
|
||||
ShortDescription string `json:"short_description"`
|
||||
CTAEnabled bool `json:"cta_enabled"`
|
||||
CTAAction string `json:"cta_action"`
|
||||
ResumeLink string `json:"resume_link"`
|
||||
About string `json:"about"`
|
||||
ContactEmail string `json:"contact_email"`
|
||||
Achievements map[string]AchievementItemDTO `json:"achievements"`
|
||||
ContactPhone string `json:"contact_phone"`
|
||||
Country string `json:"country"`
|
||||
CustomRoles string `json:"custom_roles"`
|
||||
RoleLevel string `json:"role_level"`
|
||||
SocialLinks []SocialLinkDTO `json:"social_links"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
HandleUpdatedAt time.Time `json:"handle_updated_at"`
|
||||
}
|
||||
|
||||
type RoleDTO struct {
|
||||
ID string `json:"ID"`
|
||||
Name string `json:"Name"`
|
||||
}
|
||||
|
||||
type AchievementItemDTO struct {
|
||||
Value string `json:"value"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
190
internal/dto/profile.go
Normal file
190
internal/dto/profile.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"base/pkg/validation"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CreateProfileRequest struct {
|
||||
Handle string `json:"handle"`
|
||||
PageSectionOrder map[string]int `json:"page_section_order"`
|
||||
Hero HeroDTO `json:"hero"`
|
||||
About AboutDTO `json:"about"`
|
||||
Skills []SkillDTO `json:"skills"`
|
||||
Contact ContactDTO `json:"contact"`
|
||||
PageSetting PageSettingDTO `json:"page_setting"`
|
||||
}
|
||||
|
||||
func (*CreateProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"handle": validation.Rule{
|
||||
Field: "handle",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type HeroDTO struct {
|
||||
RoleID *uuid.UUID `json:"role_id"`
|
||||
RoleLevel string `json:"role_level"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Company string `json:"company"`
|
||||
ShortDescription string `json:"short_description"`
|
||||
ResumeLink string `json:"resume_link"`
|
||||
CTAEnabled bool `json:"cta_enabled"`
|
||||
Avatar string `json:"avatar"`
|
||||
}
|
||||
|
||||
func (*HeroDTO) Schema() validation.Schema { return validation.Schema{} }
|
||||
|
||||
type AboutDTO struct {
|
||||
ProfilePicture string `json:"profile_picture"`
|
||||
About string `json:"about"`
|
||||
Achievements []AchievementDTO `json:"achievements"`
|
||||
}
|
||||
|
||||
type AchievementDTO struct {
|
||||
Title string `json:"title"`
|
||||
Value string `json:"value"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type SkillDTO struct {
|
||||
SkillName string `json:"skill_name"`
|
||||
Level string `json:"level"`
|
||||
}
|
||||
|
||||
type ContactDTO struct {
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
SocialLinks []SocialLinkDTO `json:"social_links"`
|
||||
}
|
||||
|
||||
func (*ContactDTO) Schema() validation.Schema { return validation.Schema{} }
|
||||
|
||||
type SocialLinkDTO struct {
|
||||
LinkType string `json:"link_type"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
|
||||
type PageSettingDTO struct {
|
||||
VisibilityLevel string `json:"visibility_level"`
|
||||
}
|
||||
|
||||
func (*PageSettingDTO) Schema() validation.Schema {
|
||||
return validation.Schema{}
|
||||
}
|
||||
|
||||
type UpdateProfileRequest struct {
|
||||
ID string `uri:"id"`
|
||||
Handle string `json:"handle"`
|
||||
PageSectionOrder map[string]int `json:"page_section_order"`
|
||||
Hero HeroDTO `json:"hero"`
|
||||
About AboutDTO `json:"about"`
|
||||
Skills []SkillDTO `json:"skills"`
|
||||
Contact ContactDTO `json:"contact"`
|
||||
PageSetting PageSettingDTO `json:"page_setting"`
|
||||
}
|
||||
|
||||
func (*UpdateProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{
|
||||
Field: "id",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type GetProfileRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*GetProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{
|
||||
Field: "id",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type GetProfileByHandleRequest struct {
|
||||
Handle string `uri:"handle"`
|
||||
}
|
||||
|
||||
func (*GetProfileByHandleRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"handle": validation.Rule{
|
||||
Field: "handle",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type ListProfilesRequest struct {
|
||||
RoleID *uuid.UUID `form:"role_id"`
|
||||
FirstName string `form:"first_name"`
|
||||
LastName string `form:"last_name"`
|
||||
Company string `form:"company"`
|
||||
SkillName string `form:"skill_name"`
|
||||
Page uint `form:"page"`
|
||||
PageSize uint `form:"page_size"`
|
||||
SortedBy string `form:"sorted_by"`
|
||||
Ascending bool `form:"ascending"`
|
||||
}
|
||||
|
||||
func (*ListProfilesRequest) Schema() validation.Schema {
|
||||
return validation.Schema{}
|
||||
}
|
||||
|
||||
type ProfileResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Handle string `json:"handle"`
|
||||
PageSectionOrder map[string]int `json:"page_section_order"`
|
||||
Hero HeroDTO `json:"hero"`
|
||||
About AboutDTO `json:"about"`
|
||||
Skills []SkillDTO `json:"skills"`
|
||||
Contact ContactDTO `json:"contact"`
|
||||
PageSetting PageSettingDTO `json:"page_setting"`
|
||||
}
|
||||
|
||||
type ListProfilesResponse struct {
|
||||
Profiles []ProfileResponse `json:"profiles"`
|
||||
Total int `json:"total"`
|
||||
Page uint `json:"page"`
|
||||
PageSize uint `json:"page_size"`
|
||||
}
|
||||
|
||||
type DeleteProfileRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*DeleteProfileRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{
|
||||
Field: "id",
|
||||
Type: validation.ValidationTypeString,
|
||||
Required: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SkillsUpdateRequest for PUT page-sections/skills
|
||||
type SkillsUpdateRequest struct {
|
||||
Skills []SkillDTO `json:"skills"`
|
||||
}
|
||||
|
||||
func (*SkillsUpdateRequest) Schema() validation.Schema { return validation.Schema{} }
|
||||
|
||||
// PageSectionsResponse for GET page-sections (hero, contact, skills, page_section_order)
|
||||
type PageSectionsResponse struct {
|
||||
Hero HeroDTO `json:"hero"`
|
||||
Contact ContactDTO `json:"contact"`
|
||||
Skills []SkillDTO `json:"skills"`
|
||||
PageSectionOrder map[string]int `json:"page_section_order"`
|
||||
}
|
||||
107
internal/dto/response.go
Normal file
107
internal/dto/response.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package dto
|
||||
|
||||
import "net/http"
|
||||
|
||||
// SuccessResponse represents a successful response for setting stock.
|
||||
type SuccessResponse struct {
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status" example:"200"`
|
||||
}
|
||||
|
||||
// ErrorResponse represents a generic error response.
|
||||
type ErrorResponse struct {
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status" example:"400"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
Data any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func OK() Response {
|
||||
return Response{
|
||||
Message: "OK",
|
||||
Status: http.StatusOK,
|
||||
}
|
||||
}
|
||||
|
||||
func Created(data any) Response {
|
||||
return Response{
|
||||
Message: "Created",
|
||||
Status: http.StatusCreated,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func BadRequest() Response {
|
||||
return Response{
|
||||
Message: "bad request",
|
||||
Status: http.StatusBadRequest,
|
||||
}
|
||||
}
|
||||
|
||||
func NotFound() Response {
|
||||
return Response{
|
||||
Message: "not found",
|
||||
Status: http.StatusNotFound,
|
||||
}
|
||||
}
|
||||
|
||||
func InternalServerError() Response {
|
||||
return Response{
|
||||
Message: "internal server error",
|
||||
Status: http.StatusInternalServerError,
|
||||
}
|
||||
}
|
||||
|
||||
func UnprocessableEntity() Response {
|
||||
return Response{
|
||||
Message: "unprocessable entity",
|
||||
Status: http.StatusUnprocessableEntity,
|
||||
}
|
||||
}
|
||||
|
||||
func UnprocessableEntityException() Response {
|
||||
return Response{
|
||||
Message: "unprocessable entity exception",
|
||||
Status: http.StatusUnprocessableEntity,
|
||||
}
|
||||
}
|
||||
|
||||
func Forbidden() Response {
|
||||
return Response{
|
||||
Message: "forbidden",
|
||||
Status: http.StatusForbidden,
|
||||
}
|
||||
}
|
||||
|
||||
func Unauthorized() Response {
|
||||
return Response{
|
||||
Message: "unauthorized",
|
||||
Status: http.StatusUnauthorized,
|
||||
}
|
||||
}
|
||||
|
||||
func Conflict() Response {
|
||||
return Response{
|
||||
Message: "conflict",
|
||||
Status: http.StatusConflict,
|
||||
}
|
||||
}
|
||||
|
||||
func (r Response) WithMessage(msg string) Response {
|
||||
r.Message = msg
|
||||
return r
|
||||
}
|
||||
|
||||
func (r Response) WithStatus(status int) Response {
|
||||
r.Status = status
|
||||
return r
|
||||
}
|
||||
|
||||
func (r Response) WithData(data any) Response {
|
||||
r.Data = data
|
||||
return r
|
||||
}
|
||||
50
internal/dto/role.go
Normal file
50
internal/dto/role.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package dto
|
||||
|
||||
import "base/pkg/validation"
|
||||
|
||||
type ProfileRole struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
type CreateProfileRoleRequest struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (*CreateProfileRoleRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"title": validation.Rule{Field: "title", Type: validation.ValidationTypeString, Required: true},
|
||||
"status": validation.Rule{Field: "status", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type UpdateProfileRoleRequest struct {
|
||||
ID string `uri:"id"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (*UpdateProfileRoleRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type GetProfileRoleRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*GetProfileRoleRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteProfileRoleRequest struct {
|
||||
ID string `uri:"id"`
|
||||
}
|
||||
|
||||
func (*DeleteProfileRoleRequest) Schema() validation.Schema {
|
||||
return validation.Schema{
|
||||
"id": validation.Rule{Field: "id", Type: validation.ValidationTypeString, Required: true},
|
||||
}
|
||||
}
|
||||
7
internal/dto/skill.go
Normal file
7
internal/dto/skill.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package dto
|
||||
|
||||
// Skill represents a selectable skill from the catalog (for profile skill selection).
|
||||
type Skill struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
7
internal/dto/specialist.go
Normal file
7
internal/dto/specialist.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package dto
|
||||
|
||||
type Specialist struct {
|
||||
Id string `json:"id"`
|
||||
Handle string `json:"handle"`
|
||||
Avatar string `json:"avatar"`
|
||||
}
|
||||
Reference in New Issue
Block a user