Archived
feat: monorepo structure with Django backend, React frontend, and Expo mobile app
- Backend: Django 5 + DRF with accounts, documents, collections, and reading apps - Custom User model with email-based auth, JWT via SimpleJWT - Full CRUD viewsets with ModelSerializer + DRF routers - pytest, Ruff, drf-spectacular (OpenAPI), whitenoise - Dockerfile for production deployment - Frontend: React 18 + TypeScript + Vite - Lazy-loaded routes with ProtectedRoute/PublicRoute guards - Auth context with useReducer, token refresh interceptor - Pages: Login, Register, Library, Document Detail, Reader, Collections, Settings - Dark theme, responsive grid layout, Vite proxy to Django backend - Mobile: Expo SDK 51 + React Native + Expo Router - File-based routing with login, register, and library screens - AsyncStorage for token persistence, token refresh interceptor - Shared API types via @cloud-reader/shared workspace package - Shared: TypeScript types (API responses, auth, documents, etc.) - CI/CD: 3 independent GitHub Actions pipelines (backend, frontend, mobile)
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "@cloud-reader/shared",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo 'lint ok'"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.5.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// Shared types for Cloud Reader - used by both frontend (web) and mobile (Expo)
|
||||
|
||||
// ============================================================================
|
||||
// API Response Types
|
||||
// ============================================================================
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
data: T;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
export interface ApiError {
|
||||
detail: string;
|
||||
code?: string;
|
||||
fields?: Record<string, string[]>;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Auth Types
|
||||
// ============================================================================
|
||||
|
||||
export interface LoginRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface RegisterRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
password_confirm: string;
|
||||
display_name?: string;
|
||||
}
|
||||
|
||||
export interface AuthTokens {
|
||||
access: string;
|
||||
refresh: string;
|
||||
}
|
||||
|
||||
export interface UserProfile {
|
||||
id: number;
|
||||
email: string;
|
||||
display_name: string;
|
||||
avatar_url: string | null;
|
||||
date_joined: string;
|
||||
is_verified: boolean;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Document / Reader Types
|
||||
// ============================================================================
|
||||
|
||||
export interface Document {
|
||||
id: number;
|
||||
title: string;
|
||||
author: string | null;
|
||||
cover_url: string | null;
|
||||
description: string;
|
||||
file_type: 'pdf' | 'epub' | 'mobi' | 'txt' | 'docx';
|
||||
file_size: number;
|
||||
page_count: number | null;
|
||||
uploaded_at: string;
|
||||
updated_at: string;
|
||||
tags: string[];
|
||||
is_public: boolean;
|
||||
owner: number;
|
||||
}
|
||||
|
||||
export interface DocumentDetail extends Document {
|
||||
current_page: number;
|
||||
total_pages: number;
|
||||
bookmark: Bookmark | null;
|
||||
recent_highlights: Highlight[];
|
||||
}
|
||||
|
||||
export interface Bookmark {
|
||||
id: number;
|
||||
page: number;
|
||||
label: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface Highlight {
|
||||
id: number;
|
||||
page: number;
|
||||
color: string;
|
||||
text: string;
|
||||
note: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface ReadingProgress {
|
||||
id: number;
|
||||
document: number;
|
||||
current_page: number;
|
||||
total_pages: number;
|
||||
percentage: number;
|
||||
last_read_at: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Collection / Library Types
|
||||
// ============================================================================
|
||||
|
||||
export interface Collection {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
cover_url: string | null;
|
||||
document_count: number;
|
||||
is_public: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface LibraryStats {
|
||||
total_documents: number;
|
||||
total_pages_read: number;
|
||||
total_reading_time_minutes: number;
|
||||
documents_this_month: number;
|
||||
recent_activity: ReadingActivity[];
|
||||
}
|
||||
|
||||
export interface ReadingActivity {
|
||||
date: string;
|
||||
documents_read: number;
|
||||
pages_read: number;
|
||||
minutes_read: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Constants
|
||||
// ============================================================================
|
||||
|
||||
export const SUPPORTED_FILE_TYPES = ['pdf', 'epub', 'mobi', 'txt', 'docx'] as const;
|
||||
export type SupportedFileType = typeof SUPPORTED_FILE_TYPES[number];
|
||||
|
||||
export const HIGHLIGHT_COLORS = ['yellow', 'green', 'blue', 'pink', 'orange'] as const;
|
||||
export type HighlightColor = typeof HIGHLIGHT_COLORS[number];
|
||||
|
||||
export const READING_SPEED_WPM = 250; // Average reading speed
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user