Hamdast1/ARCHITECTURE_DIAGRAM.md
2026-05-20 12:31:48 +03:30

14 KiB

Architecture Diagram - SubmitChallengePage

┌─────────────────────────────────────────────────────────────────┐
│                    User Navigates to /submit/2                   │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│              SubmitChallengePage.tsx (60 lines)                  │
│                                                                   │
│  const { topicId } = useParams();  // "2"                        │
│  const topicConfig = getTopicConfig(topicId);                    │
│                                                                   │
│  return (                                                         │
│    <Layout>                                                       │
│      <FormComponent {...props} />  ← Dynamic!                    │
│    </Layout>                                                      │
│  );                                                               │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                    topicConfig.ts (Config)                        │
│                                                                   │
│  topicConfigs["2"] = {                                            │
│    id: "2",                                                       │
│    title: "نیمکت",                                               │
│    mediaType: "both",           ← Config                         │
│    requiresTeammates: true,     ← Config                         │
│    formComponent: ImageVideoForm ← Dynamic Component             │
│  }                                                                │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│             ImageVideoForm.tsx (215 lines)                        │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  Media Type Tabs: [Image] [Video]                        │   │
│  └─────────────────────────────────────────────────────────┘   │
│                      │                                            │
│         ┌────────────┴────────────┐                             │
│         ▼                          ▼                             │
│  ┌─────────────┐          ┌─────────────┐                      │
│  │MediaUploadBox│          │MediaUploadBox│                      │
│  │(Image)       │          │(Video)       │                      │
│  │              │          │  + Cover     │                      │
│  └─────────────┘          └─────────────┘                      │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  TeammatesSection (shared)                                │   │
│  │  - Add/Remove teammate inputs                             │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  FormInput: Title (shared)                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  FormInput: Learnings (shared, multiline)                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  [ثبت نهایی چالش]  ← Submit Button                       │   │
│  └─────────────────────────────────────────────────────────┘   │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
                   onSubmit(data) → navigate(`/feed/2`)

Component Relationships

SubmitChallengePage (Container)
│
├── Background + Stars (Layout)
│
├── Fixed Header (Layout)
│   ├── Back Button
│   ├── Logo
│   ├── Coin Counter
│   └── Topic Title Bar
│
└── Dynamic Form (Config-Driven)
    │
    ├── ImageForm (Topics: 1,3,4,5,6,7,8,9)
    │   ├── MediaUploadBox (Image)
    │   ├── TeammatesSection (conditional)
    │   ├── FormInput (Title)
    │   ├── FormInput (Learnings)
    │   └── Submit Button
    │
    └── ImageVideoForm (Topic: 2)
        ├── Tab Switcher [Image|Video]
        ├── MediaUploadBox (Image or Video)
        ├── MediaUploadBox (Video Cover - conditional)
        ├── TeammatesSection
        ├── FormInput (Title)
        ├── FormInput (Learnings)
        └── Submit Button

Data Flow

┌──────────────┐
│   topicId    │  "2"
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│ getTopicConfig() │
└──────┬───────────┘
       │
       ▼
┌──────────────────────────────────┐
│ {                                 │
│   mediaType: "both",              │
│   requiresTeammates: true,        │
│   formComponent: ImageVideoForm   │
│ }                                 │
└──────┬───────────────────────────┘
       │
       ▼
┌──────────────────────┐
│  ImageVideoForm      │
│  - renders UI        │
│  - collects data     │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  handleSubmit(data)  │
│  {                   │
│    topicId: "2",     │
│    title: "...",     │
│    learnings: "...", │
│    mediaType: "...", │
│    uploadedVideo,    │
│    videoCover,       │
│    teammates: [...]  │
│  }                   │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  navigate("/feed/2") │
└──────────────────────┘

Shared Components Usage

MediaUploadBox
├── Used by: ImageForm, ImageVideoForm
├── Variants: Image upload, Video upload, Cover upload
└── Props: type, uploadedFile, onUpload, onRemove, label?, required?

TeammatesSection
├── Used by: ImageForm, ImageVideoForm
├── Controlled by: topicConfig.requiresTeammates
└── Props: teammates[], onAdd, onRemove, onChange

FormInput
├── Used by: ImageForm, ImageVideoForm
├── Variants: Single line, Multiline (textarea)
└── Props: label, value, onChange, placeholder, multiline?, rows?

Config → Component Mapping

Topic 1 (تخته سیاه)
├── mediaType: "image"
├── requiresTeammates: true
└── formComponent: ImageForm → Shows image + teammates

Topic 2 (نیمکت)  
├── mediaType: "both"
├── requiresTeammates: true
└── formComponent: ImageVideoForm → Shows tabs + teammates

Topic 3 (دفترچه یادداشت)
├── mediaType: "image"
├── requiresTeammates: false
└── formComponent: ImageForm → Shows image only

Topic 4-9 (Other topics)
├── mediaType: "image"
├── requiresTeammates: varies
└── formComponent: ImageForm → Configured per topic

Adding New Topic (Flow)

Step 1: Choose Form Type
   │
   ├── Need video? → ImageVideoForm
   ├── Just image? → ImageForm
   └── Custom? → Create new form
   │
   ▼
Step 2: Update topicConfig.ts
   │
   ├── Add topic object
   ├── Set mediaType
   ├── Set requiresTeammates
   └── Set formComponent
   │
   ▼
Step 3: Done! ✅
   │
   └── SubmitChallengePage automatically uses new config

Benefits Visualization

                 BEFORE                      AFTER
                   │                           │
    ┌──────────────▼──────────────┐   ┌───────▼────────┐
    │  SubmitChallengePage.tsx    │   │  topicConfig   │
    │         (540 lines)          │   │  (defines all) │
    │                              │   └───────┬────────┘
    │  if (topicId === "2") {     │           │
    │    // video logic            │   ┌───────▼────────┐
    │  } else {                    │   │SubmitChallenge │
    │    // image logic            │   │      Page      │
    │  }                           │   │   (60 lines)   │
    │                              │   └───────┬────────┘
    │  // All forms inline         │           │
    │  // Duplicated upload code   │   ┌───────▼────────┐
    │  // Duplicated teammates     │   │  Dynamic Form  │
    │  // Mixed concerns           │   │   Component    │
    └──────────────────────────────┘   └───────┬────────┘
                                               │
                               ┌───────────────┼───────────────┐
                               │               │               │
                         ┌─────▼─────┐  ┌─────▼─────┐  ┌─────▼─────┐
                         │ ImageForm │  │ImageVideo │  │  Shared   │
                         │           │  │   Form    │  │Components │
                         │ (90 lines)│  │(215 lines)│  │(210 lines)│
                         └───────────┘  └───────────┘  └───────────┘

File Size Comparison

BEFORE:
SubmitChallengePage.tsx ████████████████████ 540 lines

AFTER:
SubmitChallengePage.tsx ███ 60 lines
ImageForm.tsx          ████ 90 lines
ImageVideoForm.tsx     █████████ 215 lines
Shared Components      ████████ 210 lines
                       ─────────────────────
                       Total: 575 lines (better organized!)

Complexity Reduction

Cyclomatic Complexity (Fewer branches = Better)

BEFORE: ████████████████████ 20+ decision points
AFTER:  ████ 5 decision points (-75%)

Code Duplication

BEFORE: ████████████████ High (repeated upload logic)
AFTER:  █ Very Low (shared components)

Time to Add Topic

BEFORE: ███████ 30 minutes (edit main file)
AFTER:  █ 2 minutes (update config)

Visual Summary:

  • Container handles layout
  • Config drives behavior
  • Forms handle business logic
  • Shared components = DRY
  • Easy to extend
  • Type-safe