@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
683 lines (577 loc) • 13.9 kB
text/typescript
export type ReviewStatus =
| "draft"
| "pending_review"
| "under_review"
| "approved"
| "rejected"
| "published"
| "archived"
| "expired";
export type ReviewPriority = "low" | "medium" | "high" | "urgent";
export type ReviewType =
| "content_creation"
| "content_update"
| "content_deletion"
| "template_change"
| "design_update"
| "legal_compliance"
| "seo_optimization";
export type ContentType =
| "hero_section"
| "cta_section"
| "pricing_section"
| "features_section"
| "faq_section"
| "testimonial_section"
| "problem_section"
| "blog_post"
| "page"
| "template";
export type UserRole =
| "editor"
| "reviewer"
| "approver"
| "admin"
| "super_admin";
export interface ReviewItem {
id: string;
title: string;
description: string;
contentType: ContentType;
reviewType: ReviewType;
status: ReviewStatus;
priority: ReviewPriority;
// Content details
contentId: string;
siteId: string;
version: number;
currentContent: Record<string, unknown>;
proposedChanges: Record<string, unknown>;
changesSummary: string;
// Review metadata
submittedBy: string;
submittedAt: Date;
assignedTo?: string;
assignedAt?: Date;
reviewedBy?: string;
reviewedAt?: Date;
approvedBy?: string;
approvedAt?: Date;
publishedAt?: Date;
expiresAt?: Date;
archivedAt?: Date;
// Review details
reviewNotes: string;
approvalNotes: string;
rejectionReason?: string;
reviewChecklist: ReviewChecklistItem[];
// Compliance
requiresLegalReview: boolean;
requiresSEOReview: boolean;
requiresAccessibilityReview: boolean;
// Tracking
estimatedReviewTime: number; // minutes
actualReviewTime?: number; // minutes
deadlineDate?: Date;
tags: string[];
// Workflow
workflowStage: string;
nextActionRequired: string;
escalationLevel: number;
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface ReviewChecklistItem {
id: string;
category: string;
requirement: string;
checked: boolean;
checkedBy?: string;
checkedAt?: Date;
notes?: string;
required: boolean;
}
export interface ReviewWorkflow {
id: string;
name: string;
description: string;
contentTypes: ContentType[];
reviewTypes: ReviewType[];
// Workflow stages
stages: ReviewStage[];
currentStage: number;
// Configuration
autoAssignment: boolean;
parallelReview: boolean;
requireAllApprovals: boolean;
escalationEnabled: boolean;
escalationThresholdHours: number;
// Timing
slaHours: number;
reminderIntervals: number[]; // hours
// Active status
active: boolean;
version: number;
// Metadata
createdBy: string;
createdAt: Date;
updatedAt: Date;
}
export interface ReviewStage {
id: string;
name: string;
description: string;
order: number;
// Requirements
requiredRoles: UserRole[];
minimumApprovers: number;
requiredChecklist: string[];
// Timing
stageSLAHours: number;
autoApprove: boolean;
// Actions
onEntry: ReviewAction[];
onExit: ReviewAction[];
onTimeout: ReviewAction[];
onApproval: ReviewAction[];
onRejection: ReviewAction[];
}
export interface ReviewAction {
id: string;
type:
| "notify"
| "assign"
| "escalate"
| "auto_approve"
| "auto_reject"
| "webhook";
target: string;
parameters: Record<string, unknown>;
condition?: string;
}
export interface ContentCalendar {
id: string;
name: string;
description: string;
siteId: string;
// Calendar entries
entries: CalendarEntry[];
// Configuration
timezone: string;
workingDays: number[]; // 0-6 (Sunday-Saturday)
workingHours: {
start: string; // HH:mm
end: string; // HH:mm
};
// Metadata
createdBy: string;
createdAt: Date;
updatedAt: Date;
}
export interface CalendarEntry {
id: string;
title: string;
description: string;
type: "review" | "publication" | "expiration" | "audit" | "campaign";
// Timing
startDate: Date;
endDate?: Date;
allDay: boolean;
recurring: boolean;
recurrenceRule?: string; // RRULE format
// Content
contentId?: string;
reviewItemId?: string;
// Assignment
assignedTo: string[];
createdBy: string;
// Status
status: "scheduled" | "in_progress" | "completed" | "cancelled";
completedAt?: Date;
// Metadata
priority: ReviewPriority;
tags: string[];
estimatedHours: number;
actualHours?: number;
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface ContentVersion {
id: string;
contentId: string;
version: number;
// Content data
data: Record<string, unknown>;
metadata: ContentMetadata;
// Version info
changeType: "major" | "minor" | "patch";
changeDescription: string;
changelog: ChangelogEntry[];
// Status
status: ReviewStatus;
published: boolean;
current: boolean;
// Review
reviewItemId?: string;
reviewRequired: boolean;
// Tracking
createdBy: string;
createdAt: Date;
publishedAt?: Date;
archivedAt?: Date;
// Comparison
parentVersion?: number;
diff?: ContentDiff;
}
export interface ContentMetadata {
title: string;
description: string;
author: string;
lastModified: Date;
// SEO
seoTitle?: string;
seoDescription?: string;
keywords: string[];
// Lifecycle
createdDate: Date;
lastReviewDate?: Date;
nextReviewDate?: Date;
expirationDate?: Date;
// Classification
category: string;
tags: string[];
audience: string[];
// Quality
qualityScore?: number;
readabilityScore?: number;
accessibilityScore?: number;
// Performance
pageViews?: number;
engagementRate?: number;
conversionRate?: number;
}
export interface ChangelogEntry {
id: string;
timestamp: Date;
author: string;
action: string;
field?: string;
oldValue?: unknown;
newValue?: unknown;
description: string;
ipAddress?: string;
userAgent?: string;
}
export interface ContentDiff {
added: DiffItem[];
modified: DiffItem[];
removed: DiffItem[];
}
export interface DiffItem {
path: string;
field: string;
oldValue?: unknown;
newValue?: unknown;
type: "text" | "number" | "boolean" | "object" | "array";
}
export interface ReviewNotification {
id: string;
type:
| "assignment"
| "reminder"
| "escalation"
| "approval"
| "rejection"
| "publication";
// Target
recipientId: string;
recipientRole: UserRole;
// Content
title: string;
message: string;
actionUrl?: string;
// Related items
reviewItemId: string;
workflowId?: string;
calendarEntryId?: string;
// Status
sent: boolean;
sentAt?: Date;
read: boolean;
readAt?: Date;
// Configuration
priority: ReviewPriority;
channels: NotificationChannel[];
// Timestamps
createdAt: Date;
scheduledFor?: Date;
expiresAt?: Date;
}
export interface NotificationChannel {
type: "email" | "sms" | "push" | "in_app" | "slack" | "webhook";
address: string;
enabled: boolean;
preferences: Record<string, unknown>;
}
export interface ReviewAnalytics {
id: string;
period: {
start: Date;
end: Date;
};
siteId?: string;
// Performance metrics
totalReviews: number;
averageReviewTime: number; // minutes
averageApprovalTime: number; // minutes
onTimeCompletionRate: number; // percentage
// Status distribution
statusDistribution: {
[K in ReviewStatus]: number;
};
// Type distribution
typeDistribution: {
[K in ReviewType]: number;
};
// Quality metrics
rejectionRate: number; // percentage
reworkRate: number; // percentage
escalationRate: number; // percentage
// Reviewer performance
reviewerStats: ReviewerStats[];
// Content performance
contentStats: ContentStats[];
// Workflow efficiency
workflowStats: WorkflowStats[];
// Generated
generatedAt: Date;
generatedBy: string;
}
export interface ReviewerStats {
userId: string;
userName: string;
role: UserRole;
// Volume
totalReviews: number;
averageReviewTime: number;
// Quality
accuracy: number; // percentage
thoroughness: number; // percentage
// Timing
onTimeRate: number; // percentage
responseTime: number; // average hours
// Activity
activeReviews: number;
overdueTasks: number;
}
export interface ContentStats {
contentId: string;
contentType: ContentType;
// Performance
totalReviews: number;
averageReviewCycle: number; // days
// Quality
rejectionCount: number;
reworkCount: number;
// Engagement
views: number;
interactions: number;
// Lifecycle
lastUpdated: Date;
daysSinceUpdate: number;
nextReviewDue?: Date;
}
export interface WorkflowStats {
workflowId: string;
workflowName: string;
// Usage
totalExecutions: number;
averageExecutionTime: number; // hours
// Success rate
completionRate: number; // percentage
escalationRate: number; // percentage
// Stage performance
stageStats: StageStats[];
// Bottlenecks
bottleneckStages: string[];
averageWaitTime: number; // hours
}
export interface StageStats {
stageId: string;
stageName: string;
// Performance
averageTime: number; // hours
completionRate: number; // percentage
// Issues
timeoutRate: number; // percentage
rejectionRate: number; // percentage;
}
export interface ReviewSettings {
siteId: string;
// Default workflows
defaultWorkflows: {
[K in ContentType]?: string; // workflow ID
};
// Automation
autoAssignReviewers: boolean;
autoPublishApproved: boolean;
autoArchiveExpired: boolean;
// Notifications
notificationSettings: {
[K in UserRole]: NotificationPreferences;
};
// Quality requirements
qualityThresholds: {
minimumQualityScore: number;
minimumReadabilityScore: number;
minimumAccessibilityScore: number;
};
// Compliance
complianceRequirements: {
legalReviewRequired: boolean;
seoReviewRequired: boolean;
accessibilityReviewRequired: boolean;
brandGuidelinesRequired: boolean;
};
// Calendar
calendarSettings: {
timezone: string;
workingDays: number[];
workingHours: {
start: string;
end: string;
};
holidayCalendarId?: string;
};
// Retention
retentionPolicy: {
draftRetentionDays: number;
archivedRetentionDays: number;
versionRetentionCount: number;
};
// Updated
updatedBy: string;
updatedAt: Date;
}
export interface NotificationPreferences {
enabled: boolean;
channels: NotificationChannel[];
frequency: "immediate" | "hourly" | "daily" | "weekly";
quietHours: {
enabled: boolean;
start: string; // HH:mm
end: string; // HH:mm
};
events: {
[key: string]: boolean; // event type -> enabled
};
}
// API interfaces
export interface ReviewAPI {
// Review items
getReviewItem(id: string): Promise<ReviewItem>;
createReviewItem(
item: Omit<ReviewItem, "id" | "createdAt" | "updatedAt">
): Promise<ReviewItem>;
updateReviewItem(
id: string,
updates: Partial<ReviewItem>
): Promise<ReviewItem>;
deleteReviewItem(id: string): Promise<boolean>;
// Workflow management
submitForReview(
contentId: string,
reviewType: ReviewType
): Promise<ReviewItem>;
approveReview(reviewId: string, notes?: string): Promise<ReviewItem>;
rejectReview(reviewId: string, reason: string): Promise<ReviewItem>;
reassignReview(reviewId: string, assigneeId: string): Promise<ReviewItem>;
// Calendar operations
getCalendar(siteId: string): Promise<ContentCalendar>;
addCalendarEntry(
entry: Omit<CalendarEntry, "id" | "createdAt" | "updatedAt">
): Promise<CalendarEntry>;
updateCalendarEntry(
id: string,
updates: Partial<CalendarEntry>
): Promise<CalendarEntry>;
deleteCalendarEntry(id: string): Promise<boolean>;
// Version management
getContentVersions(contentId: string): Promise<ContentVersion[]>;
createVersion(
contentId: string,
data: Record<string, unknown>,
changeDescription: string
): Promise<ContentVersion>;
compareVersions(
contentId: string,
version1: number,
version2: number
): Promise<ContentDiff>;
rollbackToVersion(
contentId: string,
version: number
): Promise<ContentVersion>;
// Analytics
getReviewAnalytics(
siteId: string,
period: { start: Date; end: Date }
): Promise<ReviewAnalytics>;
getReviewerPerformance(
userId: string,
period: { start: Date; end: Date }
): Promise<ReviewerStats>;
getContentPerformance(contentId: string): Promise<ContentStats>;
// Settings
getReviewSettings(siteId: string): Promise<ReviewSettings>;
updateReviewSettings(
siteId: string,
settings: Partial<ReviewSettings>
): Promise<ReviewSettings>;
// Workflows
getWorkflows(siteId: string): Promise<ReviewWorkflow[]>;
createWorkflow(
workflow: Omit<ReviewWorkflow, "id" | "createdAt" | "updatedAt">
): Promise<ReviewWorkflow>;
updateWorkflow(
id: string,
updates: Partial<ReviewWorkflow>
): Promise<ReviewWorkflow>;
deleteWorkflow(id: string): Promise<boolean>;
}
// Search and filtering
export interface ReviewSearchQuery {
siteId?: string;
status?: ReviewStatus[];
contentType?: ContentType[];
reviewType?: ReviewType[];
assignedTo?: string;
submittedBy?: string;
priority?: ReviewPriority[];
tags?: string[];
dateRange?: {
start: Date;
end: Date;
};
search?: string;
sortBy?: "createdAt" | "updatedAt" | "priority" | "deadline" | "status";
sortOrder?: "asc" | "desc";
limit?: number;
offset?: number;
}
export interface ReviewSearchResult {
reviews: ReviewItem[];
total: number;
page: number;
limit: number;
hasMore: boolean;
facets: {
status: { [K in ReviewStatus]?: number };
contentType: { [K in ContentType]?: number };
reviewType: { [K in ReviewType]?: number };
priority: { [K in ReviewPriority]?: number };
assignees: { [key: string]: number };
};
}