tercul-frontend/shared/schema.ts
Damir Mukimov 4a23f496fa
Major frontend development updates
- Enhanced annotation system with improved inline editing
- Updated author components with new card and header designs
- Improved reading view with enhanced line numbering and controls
- Added new blog management features and tag management
- Updated UI components with improved accessibility and styling
- Enhanced search functionality with better filtering
- Added new dashboard features and activity feeds
- Improved translation selector and work comparison tools
- Updated GraphQL integration and API hooks
- Enhanced responsive design and mobile experience
2025-11-27 03:44:09 +01:00

642 lines
18 KiB
TypeScript

import { z } from "zod";
// Enums for GraphQL/API
export const roleEnum = z.enum([
"user",
"contributor",
"reviewer",
"editor",
"admin",
]);
export const workTypeEnum = z.enum([
"poem",
"story",
"novel",
"play",
"essay",
"other",
]);
export const contributionStatusEnum = z.enum([
"draft",
"submitted",
"under_review",
"approved",
"rejected",
]);
// Core entity schemas for GraphQL/API
export const userSchema = z.object({
id: z.string(),
username: z.string(),
email: z.string(),
displayName: z.string().optional(),
firstName: z.string().optional(),
lastName: z.string().optional(),
bio: z.string().optional(),
avatar: z.string().optional(),
role: roleEnum,
verified: z.boolean().optional(),
active: z.boolean().optional(),
lastLoginAt: z.string().optional(),
createdAt: z.string(), // ISO date string
updatedAt: z.string().optional(),
countryId: z.string().optional(),
cityId: z.string().optional(),
});
export const authorSchema = z.object({
id: z.string(),
name: z.string(),
slug: z.string(),
birthYear: z.number().optional(),
deathYear: z.number().optional(),
country: z.string().optional(),
biography: z.string().optional(),
portrait: z.string().optional(),
createdAt: z.string(),
createdBy: z.string().optional(),
updatedAt: z.string().optional(),
countryId: z.string().optional(),
cityId: z.string().optional(),
copyrightId: z.string().optional(),
});
export const workSchema = z.object({
id: z.string(),
title: z.string(),
slug: z.string(),
authorId: z.string(),
year: z.number().optional(),
type: workTypeEnum,
language: z.string(),
content: z.string(),
description: z.string().optional(),
createdAt: z.string(),
createdBy: z.string().optional(),
updatedAt: z.string().optional(),
tags: z.array(z.string()).optional(), // Array of tag IDs
likes: z.number().optional(),
views: z.number().optional(),
author: authorSchema.optional(), // For denormalized author info
readabilityScore: z.number().optional(),
copyrightId: z.string().optional(),
});
export const translationSchema = z.object({
id: z.string(),
workId: z.string(),
title: z.string(),
language: z.string(),
content: z.string(),
translatorId: z.string(),
year: z.number().optional(),
notes: z.string().optional(),
description: z.string().optional(),
createdAt: z.string(),
});
export const tagSchema = z.object({
id: z.string(),
name: z.string(),
type: z.string(), // genre, period, theme, etc.
createdAt: z.string(),
});
export const bookmarkSchema = z.object({
id: z.string(),
userId: z.string(),
workId: z.string(),
note: z.string().optional(),
createdAt: z.string(),
});
export const commentSchema = z.object({
id: z.string(),
userId: z.string(),
workId: z.string().optional(),
translationId: z.string().optional(),
lineNumber: z.number().optional(),
content: z.string(),
parentId: z.string().optional(),
entityType: z.string().optional(), // 'work', 'translation', 'blogPost', etc.
entityId: z.string().optional(),
createdAt: z.string(),
});
export const likeSchema = z.object({
id: z.string(),
userId: z.string(),
entityType: z.string(), // 'work', 'translation', 'comment'
entityId: z.string(),
createdAt: z.string(),
});
export const collectionSchema = z.object({
id: z.string(),
name: z.string(),
slug: z.string(),
description: z.string().optional(),
userId: z.string(),
isPublic: z.boolean(),
createdAt: z.string(),
});
export const collectionItemSchema = z.object({
id: z.string(),
collectionId: z.string(),
workId: z.string(),
order: z.number(),
addedAt: z.string(),
});
export const timelineEventSchema = z.object({
id: z.string(),
authorId: z.string(),
year: z.number(),
title: z.string(),
description: z.string().optional(),
createdAt: z.string(),
});
export const blogPostSchema = z.object({
id: z.string(),
title: z.string(),
slug: z.string(),
content: z.string(),
authorId: z.string(),
excerpt: z.string().optional(),
publishedAt: z.string().optional(),
createdAt: z.string(),
});
export const readingProgressSchema = z.object({
id: z.string(),
userId: z.string(),
workId: z.string(),
translationId: z.string().optional(),
progress: z.number().min(0).max(100), // percentage
lastReadAt: z.string(),
});
export const annotationSchema = z.object({
id: z.string(),
workId: z.string(),
translationId: z.string().optional(),
lineNumber: z.number().optional(),
content: z.string(),
type: z.string(), // 'context', 'analysis', 'translation', etc.
userId: z.string(),
isOfficial: z.boolean(),
createdAt: z.string(),
});
export const analysisResultSchema = z.object({
id: z.string(),
workId: z.string(),
type: z.string(), // 'sentiment', 'linguistics', 'themes', 'poetic', etc.
data: z.record(z.string(), z.unknown()), // flexible data structure
createdAt: z.string(),
});
// New schemas for GraphQL alignment
export const countrySchema = z.object({
id: z.string(),
name: z.string(),
code: z.string(),
language: z.string(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const citySchema = z.object({
id: z.string(),
name: z.string(),
countryId: z.string(),
language: z.string(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const bookSchema = z.object({
id: z.string(),
title: z.string(),
slug: z.string(),
language: z.string(),
authorId: z.string(),
copyrightId: z.string().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const copyrightSchema = z.object({
id: z.string(),
name: z.string(),
language: z.string(),
details: z.string().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const contributionSchema = z.object({
id: z.string(),
name: z.string(),
status: contributionStatusEnum,
userId: z.string(),
workId: z.string().optional(),
translationId: z.string().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const userProfileSchema = z.object({
id: z.string(),
userId: z.string(),
phoneNumber: z.string().optional(),
website: z.string().optional(),
twitter: z.string().optional(),
facebook: z.string().optional(),
linkedIn: z.string().optional(),
github: z.string().optional(),
preferences: z.record(z.string(), z.unknown()).optional(),
settings: z.record(z.string(), z.unknown()).optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const readabilityScoreSchema = z.object({
id: z.string(),
workId: z.string(),
score: z.number(),
language: z.string(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const writingStyleSchema = z.object({
id: z.string(),
workId: z.string(),
name: z.string(),
language: z.string(),
characteristics: z.record(z.string(), z.unknown()).optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const emotionSchema = z.object({
id: z.string(),
name: z.string(),
workId: z.string().optional(),
userId: z.string().optional(),
collectionId: z.string().optional(),
language: z.string(),
intensity: z.number().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const conceptSchema = z.object({
id: z.string(),
name: z.string(),
description: z.string().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const topicClusterSchema = z.object({
id: z.string(),
name: z.string(),
description: z.string().optional(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const workStatsSchema = z.object({
id: z.string(),
workId: z.string(),
views: z.number(),
likes: z.number(),
bookmarks: z.number(),
comments: z.number(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
export const userStatsSchema = z.object({
id: z.string(),
userId: z.string(),
activity: z.number(),
contributions: z.number(),
likes: z.number(),
comments: z.number(),
createdAt: z.string(),
updatedAt: z.string().optional(),
});
// Input schemas for GraphQL mutations/API endpoints
export const createUserSchema = userSchema.omit({
id: true,
createdAt: true,
role: true, // Role assigned by system
});
export const createAuthorSchema = authorSchema.omit({
id: true,
createdAt: true,
});
export const createWorkSchema = workSchema.omit({
id: true,
createdAt: true,
author: true, // Not included in creation
});
export const createTranslationSchema = translationSchema.omit({
id: true,
createdAt: true,
});
export const createTagSchema = tagSchema.omit({
id: true,
createdAt: true,
});
export const createBookmarkSchema = bookmarkSchema.omit({
id: true,
createdAt: true,
});
export const createCommentSchema = commentSchema.omit({
id: true,
createdAt: true,
});
export const createLikeSchema = likeSchema.omit({
id: true,
createdAt: true,
});
export const createCollectionSchema = collectionSchema.omit({
id: true,
createdAt: true,
});
export const createCollectionItemSchema = collectionItemSchema.omit({
id: true,
addedAt: true,
});
export const createTimelineEventSchema = timelineEventSchema.omit({
id: true,
createdAt: true,
});
export const createBlogPostSchema = blogPostSchema.omit({
id: true,
createdAt: true,
});
export const createReadingProgressSchema = readingProgressSchema.omit({
id: true,
lastReadAt: true,
});
export const createAnnotationSchema = annotationSchema.omit({
id: true,
createdAt: true,
});
export const createAnalysisResultSchema = analysisResultSchema.omit({
id: true,
createdAt: true,
});
// New create schemas for GraphQL alignment
export const createCountrySchema = countrySchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createCitySchema = citySchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createBookSchema = bookSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createCopyrightSchema = copyrightSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createContributionSchema = contributionSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createUserProfileSchema = userProfileSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createReadabilityScoreSchema = readabilityScoreSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createWritingStyleSchema = writingStyleSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createEmotionSchema = emotionSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createConceptSchema = conceptSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createTopicClusterSchema = topicClusterSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createWorkStatsSchema = workStatsSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const createUserStatsSchema = userStatsSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
// Update schemas for partial updates
export const updateUserSchema = createUserSchema.partial();
export const updateAuthorSchema = createAuthorSchema.partial();
export const updateWorkSchema = createWorkSchema.partial();
export const updateTranslationSchema = createTranslationSchema.partial();
export const updateTagSchema = createTagSchema.partial();
export const updateBookmarkSchema = createBookmarkSchema.partial();
export const updateCommentSchema = createCommentSchema.partial();
export const updateCollectionSchema = createCollectionSchema.partial();
export const updateTimelineEventSchema = createTimelineEventSchema.partial();
export const updateBlogPostSchema = createBlogPostSchema.partial();
export const updateReadingProgressSchema =
createReadingProgressSchema.partial();
export const updateAnnotationSchema = createAnnotationSchema.partial();
// New update schemas for GraphQL alignment
export const updateCountrySchema = createCountrySchema.partial();
export const updateCitySchema = createCitySchema.partial();
export const updateBookSchema = createBookSchema.partial();
export const updateCopyrightSchema = createCopyrightSchema.partial();
export const updateContributionSchema = createContributionSchema.partial();
export const updateUserProfileSchema = createUserProfileSchema.partial();
export const updateReadabilityScoreSchema =
createReadabilityScoreSchema.partial();
export const updateWritingStyleSchema = createWritingStyleSchema.partial();
export const updateEmotionSchema = createEmotionSchema.partial();
export const updateConceptSchema = createConceptSchema.partial();
export const updateTopicClusterSchema = createTopicClusterSchema.partial();
export const updateWorkStatsSchema = createWorkStatsSchema.partial();
export const updateUserStatsSchema = createUserStatsSchema.partial();
// TypeScript types inferred from Zod schemas
export type User = z.infer<typeof userSchema>;
export type Author = z.infer<typeof authorSchema>;
export type Work = z.infer<typeof workSchema>;
export type Translation = z.infer<typeof translationSchema>;
export type Tag = z.infer<typeof tagSchema>;
export type Bookmark = z.infer<typeof bookmarkSchema>;
export type Comment = z.infer<typeof commentSchema>;
export type Like = z.infer<typeof likeSchema>;
export type Collection = z.infer<typeof collectionSchema>;
export type CollectionItem = z.infer<typeof collectionItemSchema>;
export type TimelineEvent = z.infer<typeof timelineEventSchema>;
export type BlogPost = z.infer<typeof blogPostSchema>;
export type ReadingProgress = z.infer<typeof readingProgressSchema>;
export type Annotation = z.infer<typeof annotationSchema>;
export type AnalysisResult = z.infer<typeof analysisResultSchema>;
// New types for GraphQL alignment
export type Country = z.infer<typeof countrySchema>;
export type City = z.infer<typeof citySchema>;
export type Book = z.infer<typeof bookSchema>;
export type Copyright = z.infer<typeof copyrightSchema>;
export type Contribution = z.infer<typeof contributionSchema>;
export type UserProfile = z.infer<typeof userProfileSchema>;
export type ReadabilityScore = z.infer<typeof readabilityScoreSchema>;
export type WritingStyle = z.infer<typeof writingStyleSchema>;
export type Emotion = z.infer<typeof emotionSchema>;
export type Concept = z.infer<typeof conceptSchema>;
export type TopicCluster = z.infer<typeof topicClusterSchema>;
export type WorkStats = z.infer<typeof workStatsSchema>;
export type UserStats = z.infer<typeof userStatsSchema>;
// Input types
export type CreateUser = z.infer<typeof createUserSchema>;
export type CreateAuthor = z.infer<typeof createAuthorSchema>;
export type CreateWork = z.infer<typeof createWorkSchema>;
export type CreateTranslation = z.infer<typeof createTranslationSchema>;
export type CreateTag = z.infer<typeof createTagSchema>;
export type CreateBookmark = z.infer<typeof createBookmarkSchema>;
export type CreateComment = z.infer<typeof createCommentSchema>;
export type CreateLike = z.infer<typeof createLikeSchema>;
export type CreateCollection = z.infer<typeof createCollectionSchema>;
export type CreateCollectionItem = z.infer<typeof createCollectionItemSchema>;
export type CreateTimelineEvent = z.infer<typeof createTimelineEventSchema>;
export type CreateBlogPost = z.infer<typeof createBlogPostSchema>;
export type CreateReadingProgress = z.infer<typeof createReadingProgressSchema>;
export type CreateAnnotation = z.infer<typeof createAnnotationSchema>;
export type CreateAnalysisResult = z.infer<typeof createAnalysisResultSchema>;
// New create types for GraphQL alignment
export type CreateCountry = z.infer<typeof createCountrySchema>;
export type CreateCity = z.infer<typeof createCitySchema>;
export type CreateBook = z.infer<typeof createBookSchema>;
export type CreateCopyright = z.infer<typeof createCopyrightSchema>;
export type CreateContribution = z.infer<typeof createContributionSchema>;
export type CreateUserProfile = z.infer<typeof createUserProfileSchema>;
export type CreateReadabilityScore = z.infer<
typeof createReadabilityScoreSchema
>;
export type CreateWritingStyle = z.infer<typeof createWritingStyleSchema>;
export type CreateEmotion = z.infer<typeof createEmotionSchema>;
export type CreateConcept = z.infer<typeof createConceptSchema>;
export type CreateTopicCluster = z.infer<typeof createTopicClusterSchema>;
export type CreateWorkStats = z.infer<typeof createWorkStatsSchema>;
export type CreateUserStats = z.infer<typeof createUserStatsSchema>;
// Update types
export type UpdateUser = z.infer<typeof updateUserSchema>;
export type UpdateAuthor = z.infer<typeof updateAuthorSchema>;
export type UpdateWork = z.infer<typeof updateWorkSchema>;
export type UpdateTranslation = z.infer<typeof updateTranslationSchema>;
export type UpdateTag = z.infer<typeof updateTagSchema>;
export type UpdateBookmark = z.infer<typeof updateBookmarkSchema>;
export type UpdateComment = z.infer<typeof updateCommentSchema>;
export type UpdateCollection = z.infer<typeof updateCollectionSchema>;
export type UpdateTimelineEvent = z.infer<typeof updateTimelineEventSchema>;
export type UpdateBlogPost = z.infer<typeof updateBlogPostSchema>;
export type UpdateReadingProgress = z.infer<typeof updateReadingProgressSchema>;
export type UpdateAnnotation = z.infer<typeof updateAnnotationSchema>;
// New update types for GraphQL alignment
export type UpdateCountry = z.infer<typeof updateCountrySchema>;
export type UpdateCity = z.infer<typeof updateCitySchema>;
export type UpdateBook = z.infer<typeof updateBookSchema>;
export type UpdateCopyright = z.infer<typeof updateCopyrightSchema>;
export type UpdateContribution = z.infer<typeof updateContributionSchema>;
export type UpdateUserProfile = z.infer<typeof updateUserProfileSchema>;
export type UpdateReadabilityScore = z.infer<
typeof updateReadabilityScoreSchema
>;
export type UpdateWritingStyle = z.infer<typeof updateWritingStyleSchema>;
export type UpdateEmotion = z.infer<typeof updateEmotionSchema>;
export type UpdateConcept = z.infer<typeof updateConceptSchema>;
export type UpdateTopicCluster = z.infer<typeof updateTopicClusterSchema>;
export type UpdateWorkStats = z.infer<typeof updateWorkStatsSchema>;
export type UpdateUserStats = z.infer<typeof updateUserStatsSchema>;
// API Response schemas
export const apiResponseSchema = z.object({
success: z.boolean(),
data: z.unknown().optional(),
error: z.string().optional(),
message: z.string().optional(),
});
export const paginatedResponseSchema = z.object({
data: z.array(z.unknown()),
pagination: z.object({
page: z.number(),
limit: z.number(),
total: z.number(),
totalPages: z.number(),
}),
});
export type ApiResponse = z.infer<typeof apiResponseSchema>;
export type PaginatedResponse = z.infer<typeof paginatedResponseSchema>;