לדלג לתוכן

6.10 פרויקטים פרויקט

פרויקטים - ריאקט בסיסי

הפרויקטים הבאים משלבים את כל מה שלמדנו בפרק הזה: קומפוננטות, props, סטייט, אירועים, רינדור מותנה, רשימות, טפסים, ו-useEffect. כל פרויקט צריך להיבנות עם טייפסקריפט, בגישת "חשיבה בריאקט" - פירוק לקומפוננטות, סטייט מינימלי, ו-composition.


פרויקט 1 - אפליקציית משימות - Todo App

בנו אפליקציית משימות מלאה עם CRUD, סינון, ושמירה מקומית.

דרישות פונקציונליות

  • הוספת משימה חדשה עם טקסט ועדיפות (low/medium/high)
  • סימון משימה כהושלמה (toggle)
  • עריכת טקסט של משימה קיימת (inline editing)
  • מחיקת משימה
  • סינון: הכל / פעילות / הושלמו
  • סינון לפי עדיפות
  • מיון: לפי תאריך יצירה / לפי עדיפות
  • חיפוש חופשי בטקסט המשימות
  • מונה: X פעילות מתוך Y
  • כפתור "נקה הושלמו" שמוחק את כל המשימות שהושלמו
  • שמירה ב-localStorage - המשימות נשמרות ונטענות בין רענונים

מבנה קומפוננטות

TodoApp
  AddTodoForm
  FilterBar
  SearchBox
  TodoList
    TodoItem
  TodoStats

דרישות טכניות

  • כל קומפוננטה בקובץ נפרד עם interfaces מפורשים ל-props
  • טיפוסים מוגדרים בקובץ types.ts
  • שמירה ב-localStorage עם useEffect
  • טעינה מ-localStorage עם lazy initializer ב-useState
  • כל משימה עם id ייחודי (השתמשו ב-Date.now() או מונה)
  • עדיפויות מוצגות בצבעים שונים

טיפוסים

interface Todo {
    id: number;
    text: string;
    done: boolean;
    priority: "low" | "medium" | "high";
    createdAt: string;
}

type Filter = "all" | "active" | "completed";
type PriorityFilter = "all" | "low" | "medium" | "high";
type SortBy = "date" | "priority";

נקודות לתשומת לב

  • הפרידו בין סטייט מקומי (input של הטופס) לסטייט משותף (רשימת המשימות)
  • filteredTodos הוא ערך מחושב, לא סטייט
  • inline editing: כשלוחצים "ערוך", ה-TodoItem הופך ל-input. כשלוחצים "שמור" או Enter, חוזר לטקסט
  • השתמשו בעדכון פונקציונלי (prev => ...) כשמעדכנים מערך

פרויקט 2 - אפליקציית מזג אוויר - Weather App

בנו אפליקציית מזג אוויר שמאפשרת לחפש מזג אוויר לפי עיר ולשמור ערים מועדפות.

דרישות פונקציונליות

  • שדה חיפוש עיר עם כפתור חיפוש
  • הצגת מזג אוויר: טמפרטורה, תיאור, לחות, רוח, אייקון
  • מצבי טעינה ושגיאה
  • כפתור "הוסף למועדפים" שמוסיף את העיר לרשימה
  • רשימת ערים מועדפות - לחיצה על עיר טוענת את מזג האוויר שלה
  • מחיקת עיר מהמועדפים
  • מתג צלסיוס/פרנהייט
  • שמירת המועדפים וההעדפות ב-localStorage

מבנה קומפוננטות

WeatherApp
  SearchBar
  WeatherCard
    WeatherDetails
    TemperatureToggle
  FavoritesList
    FavoriteItem
  ErrorMessage
  LoadingSpinner

דרישות טכניות

  • שליפת נתונים עם useEffect ו-fetch
  • שימוש ב-API חינמי למזג אוויר (wttr.in format JSON: https://wttr.in/{city}?format=j1 או OpenWeatherMap)
  • AbortController לביטול בקשות
  • ניהול שלושה מצבים: loading, error, success
  • שמירה ב-localStorage: רשימת מועדפים + העדפת יחידות

טיפוסים

interface WeatherData {
    city: string;
    temperature: number;
    description: string;
    humidity: number;
    windSpeed: number;
    icon: string;
}

type TemperatureUnit = "celsius" | "fahrenheit";

type FetchStatus = "idle" | "loading" | "success" | "error";

interface AppState {
    weather: WeatherData | null;
    status: FetchStatus;
    error: string | null;
    favorites: string[];
    unit: TemperatureUnit;
}

נקודות לתשומת לב

  • הפרידו את קריאת ה-API לפונקציה נפרדת
  • טפלו ב-AbortController ב-cleanup של useEffect
  • המרת טמפרטורה היא חישוב, לא סטייט - שמרו את הטמפרטורה בצלסיוס והמירו בזמן הצגה
  • ודאו שהחיפוש מטפל בעיר לא קיימת

פרויקט 3 - אפליקציית חידון - Quiz App

בנו אפליקציית חידון אינטראקטיבית עם ניקוד, טיימר, ומעקב אחר תשובות.

דרישות פונקציונליות

  • מסך פתיחה: שם המשתתף ובחירת קטגוריה (או "הכל")
  • שאלות מוצגות אחת אחרי השנייה
  • כל שאלה: טקסט השאלה ו-4 אפשרויות תשובה
  • חיווי מיידי אם התשובה נכונה או שגויה (ירוק/אדום)
  • אי אפשר לשנות תשובה אחרי בחירה
  • טיימר של 15 שניות לכל שאלה - אם נגמר הזמן, עוברים לשאלה הבאה עם תשובה שגויה
  • כפתור "הבא" שמופיע אחרי בחירת תשובה
  • סרגל התקדמות (שאלה 3 מתוך 10)
  • מסך סיכום: ציון, מספר תשובות נכונות, זמן ממוצע לתשובה
  • אפשרות לראות את כל השאלות עם התשובות (מה בחרת ומה נכון)
  • כפתור "התחל מחדש"
  • שמירת שיא אישי ב-localStorage

מבנה קומפוננטות

QuizApp
  StartScreen
  QuizScreen
    ProgressBar
    Timer
    QuestionCard
      AnswerOption
    NextButton
  ResultScreen
    ScoreSummary
    AnswerReview

דרישות טכניות

  • שאלות מוגדרות במערך (hardcoded, לפחות 15 שאלות ב-3 קטגוריות)
  • useEffect לטיימר עם cleanup של setInterval
  • סטייט לניהול מצב המשחק: start, playing, finished
  • ערבוב שאלות וסדר תשובות בכל משחק חדש
  • שמירת היסטוריית תשובות לצורך מסך הסיכום

טיפוסים

interface Question {
    id: number;
    text: string;
    options: string[];
    correctIndex: number;
    category: string;
}

interface Answer {
    questionId: number;
    selectedIndex: number | null;
    isCorrect: boolean;
    timeSpent: number;
}

type GameState = "start" | "playing" | "finished";

interface QuizState {
    playerName: string;
    gameState: GameState;
    questions: Question[];
    currentIndex: number;
    answers: Answer[];
    timeLeft: number;
}

נקודות לתשומת לב

  • הטיימר צריך cleanup כשהקומפוננטה נמחקת או כשעוברים לשאלה הבאה
  • סטייט המשחק (GameState) קובע מה מוצג - שימוש ב-conditional rendering
  • ערבוב מערך: [...array].sort(() => Math.random() - 0.5)
  • זמן ממוצע הוא חישוב מהתשובות, לא סטייט
  • currentQuestion מחושב מ-questions[currentIndex], לא סטייט נפרד

הנחיות כלליות

  • כתבו את כל הקוד בטייפסקריפט עם טיפוסים מפורשים
  • לכל קומפוננטה קובץ נפרד
  • טיפוסים משותפים בקובץ types.ts
  • עקבו אחרי עקרונות "חשיבה בריאקט": פירוק, סטייט מינימלי, composition
  • טפלו במקרי קצה: רשימה ריקה, שגיאות, טעינה
  • השתמשו ב-CSS פשוט (inline styles מספיק, או קובץ CSS אחד)