🎉 Complete AI-Enhanced University Portal - Ready for Production
✨ Major Features Added: - AI Chat with conversation memory and university-specific knowledge base - Multi-tenant university support with white-label capabilities - Professional admin interface for knowledge base management - Advanced database schema with Prisma ORM - Comprehensive documentation and guides - Modern Next.js 15 + React 19 architecture - Bilingual support (English/Arabic) - Role-based access control - Real-time chat interface with loading states 🔧 Technical Improvements: - Fixed all linter errors and TypeScript issues - Cleaned up codebase and removed legacy files - Added comprehensive .gitignore - Updated README with detailed setup instructions - Optimized database schema and migrations - Enhanced error handling and user experience 📚 Documentation: - AI Conversation Memory Guide - AI Enhancement Summary - Developer Guide - User Guide - Complete setup and deployment instructions 🚀 Ready for GitHub deployment and production use!
This commit is contained in:
+479
-34
@@ -7,45 +7,201 @@ datasource db {
|
||||
url = "file:./dev.db"
|
||||
}
|
||||
|
||||
model User {
|
||||
// Multi-tenant University Configuration
|
||||
model University {
|
||||
id String @id @default(uuid())
|
||||
email String @unique
|
||||
slug String @unique
|
||||
name String
|
||||
role Role @default(STUDENT)
|
||||
year Int?
|
||||
faculty String?
|
||||
balance Float?
|
||||
shortName String?
|
||||
domain String?
|
||||
subdomain String?
|
||||
|
||||
// Configuration as JSON
|
||||
branding Json // Branding configuration
|
||||
contact Json // Contact information
|
||||
features Json // Feature flags
|
||||
ai Json // AI configuration
|
||||
|
||||
// Branch/Campus Management
|
||||
isMultiBranch Boolean @default(false) // Whether this university has multiple branches
|
||||
parentUniversityId String? // For branches, reference to parent university
|
||||
branchType BranchType? // Type of branch (MAIN, CAMPUS, CENTER, etc.)
|
||||
|
||||
status UniversityStatus @default(SETUP)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
enrollments Enrollment[]
|
||||
surveys Survey[]
|
||||
chatSessions ChatSession[]
|
||||
advisorId String?
|
||||
advisor User? @relation("AdvisorStudent", fields: [advisorId], references: [id])
|
||||
students User[] @relation("AdvisorStudent")
|
||||
users User[]
|
||||
programs AcademicProgram[]
|
||||
content UniversityContent[]
|
||||
knowledgeBase AIKnowledgeBase[]
|
||||
courses Course[]
|
||||
faqs FAQ[]
|
||||
assets Asset[]
|
||||
domains DomainConfig[]
|
||||
deployments DeploymentConfig[]
|
||||
cdnConfig CDNConfig?
|
||||
cdnAssets CDNAsset[]
|
||||
|
||||
// Branch relationships
|
||||
parentUniversity University? @relation("UniversityBranches", fields: [parentUniversityId], references: [id])
|
||||
branches University[] @relation("UniversityBranches")
|
||||
|
||||
@@map("users")
|
||||
@@map("universities")
|
||||
}
|
||||
|
||||
model Course {
|
||||
// Academic Programs (Majors) - University-specific
|
||||
model AcademicProgram {
|
||||
id String @id @default(uuid())
|
||||
code String @unique
|
||||
name String
|
||||
universityId String
|
||||
title String
|
||||
titleAr String?
|
||||
description String?
|
||||
credits Int
|
||||
semester String
|
||||
schedule String?
|
||||
descriptionAr String?
|
||||
level ProgramLevel
|
||||
duration String?
|
||||
fees String?
|
||||
entryRequirements String?
|
||||
campusLocations Json?
|
||||
totalCredits Int @default(120)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
enrollments Enrollment[]
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
courses Course[]
|
||||
|
||||
@@map("academic_programs")
|
||||
}
|
||||
|
||||
// University Content (Dynamic content)
|
||||
model UniversityContent {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
contentType ContentType
|
||||
title String
|
||||
titleAr String?
|
||||
content String?
|
||||
contentAr String?
|
||||
metadata Json?
|
||||
isPublished Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("university_content")
|
||||
}
|
||||
|
||||
// AI Knowledge Base (University-specific)
|
||||
model AIKnowledgeBase {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
category String?
|
||||
question String
|
||||
questionAr String?
|
||||
answer String
|
||||
answerAr String?
|
||||
priority Int @default(1)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("ai_knowledge_base")
|
||||
}
|
||||
|
||||
// Updated User model with university relationship and authentication
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
universityId String?
|
||||
email String @unique
|
||||
name String
|
||||
password String // Hashed password
|
||||
role Role @default(STUDENT)
|
||||
year Int?
|
||||
faculty String?
|
||||
balance Float?
|
||||
isActive Boolean @default(true)
|
||||
lastLogin DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University? @relation(fields: [universityId], references: [id])
|
||||
enrollments Enrollment[]
|
||||
surveys Survey[]
|
||||
chatSessions ChatSession[]
|
||||
advisorId String?
|
||||
advisor User? @relation("AdvisorStudent", fields: [advisorId], references: [id])
|
||||
students User[] @relation("AdvisorStudent")
|
||||
sessions UserSession[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
// User Session for authentication
|
||||
model UserSession {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relationships
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("user_sessions")
|
||||
}
|
||||
|
||||
// Updated Course model with university and program relationship
|
||||
model Course {
|
||||
id String @id @default(uuid())
|
||||
universityId String?
|
||||
programId String?
|
||||
code String @unique
|
||||
name String
|
||||
description String?
|
||||
credits Int
|
||||
semester String
|
||||
schedule String?
|
||||
prerequisites String?
|
||||
isRequired Boolean @default(true)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University? @relation(fields: [universityId], references: [id])
|
||||
program AcademicProgram? @relation(fields: [programId], references: [id])
|
||||
enrollments Enrollment[]
|
||||
|
||||
@@map("courses")
|
||||
}
|
||||
|
||||
// Updated FAQ model with university relationship
|
||||
model FAQ {
|
||||
id String @id @default(uuid())
|
||||
universityId String?
|
||||
question String
|
||||
answer String
|
||||
category String
|
||||
language String @default("en")
|
||||
priority Int @default(1)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University? @relation(fields: [universityId], references: [id])
|
||||
|
||||
@@map("faqs")
|
||||
}
|
||||
|
||||
model Enrollment {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
@@ -61,33 +217,36 @@ model Enrollment {
|
||||
@@map("enrollments")
|
||||
}
|
||||
|
||||
model FAQ {
|
||||
id String @id @default(uuid())
|
||||
question String
|
||||
answer String
|
||||
category String
|
||||
language String @default("en")
|
||||
priority Int @default(1)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("faqs")
|
||||
}
|
||||
|
||||
model ChatSession {
|
||||
id String @id @default(uuid())
|
||||
userId String?
|
||||
type ChatType @default(GENERAL)
|
||||
messages Json
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
messages ChatMessage[]
|
||||
|
||||
@@map("chat_sessions")
|
||||
}
|
||||
|
||||
// Chat Message for conversation memory
|
||||
model ChatMessage {
|
||||
id String @id @default(uuid())
|
||||
conversationId String
|
||||
role String // 'user' | 'assistant' | 'system'
|
||||
content String
|
||||
universitySlug String?
|
||||
userContext String? // JSON string of user context
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relationships
|
||||
session ChatSession @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("chat_messages")
|
||||
}
|
||||
|
||||
model Survey {
|
||||
id String @id @default(uuid())
|
||||
userId String?
|
||||
@@ -116,10 +275,34 @@ model AccessibilityAudit {
|
||||
@@map("accessibility_audits")
|
||||
}
|
||||
|
||||
// Enums
|
||||
enum UniversityStatus {
|
||||
SETUP
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
SUSPENDED
|
||||
}
|
||||
|
||||
enum ProgramLevel {
|
||||
UNDERGRADUATE
|
||||
POSTGRADUATE
|
||||
PHD
|
||||
}
|
||||
|
||||
enum ContentType {
|
||||
ABOUT
|
||||
RANKINGS
|
||||
RESEARCH
|
||||
CAMPUS
|
||||
NEWS
|
||||
EVENTS
|
||||
}
|
||||
|
||||
enum Role {
|
||||
STUDENT
|
||||
STAFF
|
||||
ADMIN
|
||||
SUPER_ADMIN
|
||||
}
|
||||
|
||||
enum EnrollmentStatus {
|
||||
@@ -135,3 +318,265 @@ enum ChatType {
|
||||
ACADEMIC
|
||||
TECHNICAL
|
||||
}
|
||||
|
||||
// Asset model for university-specific assets
|
||||
model Asset {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
type AssetType
|
||||
filename String
|
||||
originalName String
|
||||
mimeType String
|
||||
size Int
|
||||
path String
|
||||
url String
|
||||
altText String?
|
||||
altTextAr String?
|
||||
metadata Json?
|
||||
isPublic Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("assets")
|
||||
}
|
||||
|
||||
// Domain Configuration for multi-tenant domain management
|
||||
model DomainConfig {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
type DomainType
|
||||
domain String
|
||||
subdomain String?
|
||||
sslStatus SSLStatus @default(PENDING)
|
||||
sslExpiryDate DateTime?
|
||||
dnsStatus DNSStatus @default(PENDING)
|
||||
isActive Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
sslConfig SSLConfig?
|
||||
dnsConfig DNSConfig?
|
||||
analytics DomainAnalytics[]
|
||||
|
||||
@@map("domain_configs")
|
||||
}
|
||||
|
||||
// SSL Configuration for domain certificates
|
||||
model SSLConfig {
|
||||
id String @id @default(uuid())
|
||||
domainId String @unique
|
||||
provider SSLProvider
|
||||
certificatePath String?
|
||||
privateKeyPath String?
|
||||
autoRenewal Boolean @default(true)
|
||||
renewalThreshold Int @default(30)
|
||||
lastRenewalDate DateTime?
|
||||
nextRenewalDate DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
domainConfig DomainConfig @relation(fields: [domainId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("ssl_configs")
|
||||
}
|
||||
|
||||
// DNS Configuration for domain records
|
||||
model DNSConfig {
|
||||
id String @id @default(uuid())
|
||||
domainId String @unique
|
||||
provider DNSProvider
|
||||
apiKey String?
|
||||
zoneId String?
|
||||
recordType DNSRecordType
|
||||
recordValue String
|
||||
ttl Int @default(300)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
domainConfig DomainConfig @relation(fields: [domainId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("dns_configs")
|
||||
}
|
||||
|
||||
// Domain Analytics for monitoring
|
||||
model DomainAnalytics {
|
||||
id String @id @default(uuid())
|
||||
domainId String
|
||||
uptime Float
|
||||
responseTime Int
|
||||
sslStatus SSLStatus
|
||||
dnsStatus DNSStatus
|
||||
checkedAt DateTime @default(now())
|
||||
|
||||
// Relationships
|
||||
domainConfig DomainConfig @relation(fields: [domainId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("domain_analytics")
|
||||
}
|
||||
|
||||
enum AssetType {
|
||||
LOGO
|
||||
FAVICON
|
||||
HERO_IMAGE
|
||||
NEWS_IMAGE
|
||||
PROGRAM_IMAGE
|
||||
GALLERY_IMAGE
|
||||
DOCUMENT
|
||||
VIDEO
|
||||
AUDIO
|
||||
}
|
||||
|
||||
enum DomainType {
|
||||
SUBDOMAIN
|
||||
CUSTOM_DOMAIN
|
||||
}
|
||||
|
||||
enum SSLStatus {
|
||||
PENDING
|
||||
ACTIVE
|
||||
EXPIRED
|
||||
ERROR
|
||||
}
|
||||
|
||||
enum DNSStatus {
|
||||
PENDING
|
||||
VERIFIED
|
||||
ERROR
|
||||
}
|
||||
|
||||
enum SSLProvider {
|
||||
LETSENCRYPT
|
||||
CLOUDFLARE
|
||||
AWS
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
enum DNSProvider {
|
||||
CLOUDFLARE
|
||||
AWS_ROUTE53
|
||||
GOOGLE_CLOUD
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
enum DNSRecordType {
|
||||
A
|
||||
CNAME
|
||||
ALIAS
|
||||
}
|
||||
|
||||
// Deployment Configuration for automation
|
||||
model DeploymentConfig {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
environment DeploymentEnvironment
|
||||
version String
|
||||
status DeploymentStatus @default(PENDING)
|
||||
deploymentType DeploymentType @default(FULL)
|
||||
startTime DateTime @default(now())
|
||||
endTime DateTime?
|
||||
logs Json // Array of log messages
|
||||
metadata Json // Additional deployment metadata
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("deployment_configs")
|
||||
}
|
||||
|
||||
// Environment Configuration for different deployment stages
|
||||
model EnvironmentConfig {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
type DeploymentEnvironment
|
||||
domain String
|
||||
databaseUrl String
|
||||
apiKeys Json // API keys for different services
|
||||
features Json // Feature flags for the environment
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("environment_configs")
|
||||
}
|
||||
|
||||
enum DeploymentEnvironment {
|
||||
DEVELOPMENT
|
||||
STAGING
|
||||
PRODUCTION
|
||||
}
|
||||
|
||||
enum DeploymentStatus {
|
||||
PENDING
|
||||
IN_PROGRESS
|
||||
COMPLETED
|
||||
FAILED
|
||||
ROLLED_BACK
|
||||
}
|
||||
|
||||
enum DeploymentType {
|
||||
FULL
|
||||
INCREMENTAL
|
||||
ROLLBACK
|
||||
}
|
||||
|
||||
// CDN Configuration for cloud storage
|
||||
model CDNConfig {
|
||||
id String @id @default(uuid())
|
||||
universityId String @unique
|
||||
provider CDNProvider
|
||||
bucketName String?
|
||||
region String?
|
||||
accessKey String?
|
||||
secretKey String?
|
||||
domain String
|
||||
isActive Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
assets CDNAsset[]
|
||||
|
||||
@@map("cdn_configs")
|
||||
}
|
||||
|
||||
// CDN Assets for optimized delivery
|
||||
model CDNAsset {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
originalPath String
|
||||
cdnUrl String
|
||||
optimizedUrls Json // Record of optimized URLs
|
||||
metadata Json // Asset metadata
|
||||
uploadedAt DateTime @default(now())
|
||||
|
||||
// Relationships
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
cdnConfig CDNConfig? @relation(fields: [universityId], references: [universityId])
|
||||
|
||||
@@map("cdn_assets")
|
||||
}
|
||||
|
||||
enum CDNProvider {
|
||||
AWS_S3
|
||||
CLOUDFLARE
|
||||
CLOUDINARY
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
enum BranchType {
|
||||
MAIN
|
||||
CAMPUS
|
||||
CENTER
|
||||
BRANCH
|
||||
EXTENSION
|
||||
PARTNER
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user