Założenia
- dodawanie zleceń: klient, model, IMEI/SN, opis usterki, status, koszt, daty
- lista zleceń z filtrem po roku, miesiącu i statusie
- automatyczna „Suma miesiąca” (tylko naprawy zakończone w wybranym miesiącu)
- zapis/odczyt do JSON w AppData użytkownika
- walidacja „na żywo”, komendy, ICollectionView.Filter
1. Cel aplikacji
Napisz aplikację WPF „SerwisIphoneWpf”, która pozwala:
- dodawać zlecenia serwisowe: Klient, Model, IMEI/SN, OpisUsterki, Status, Koszt (≥ 0), DataPrzyjecia, TerminDo, DataZakonczenia (opcjonalnie), CzyOplacone
- przeglądać i filtrować listę po: Roku, Miesiącu (1–12) oraz Statusie
- liczyć „Suma miesiąca” = suma Kosztów zleceń zakończonych w wskazanym roku i miesiącu
- zapisać/wczytać listę do pliku JSON w katalogu danych użytkownika
2. Wymagania funkcjonalne
Formularz „Nowe zlecenie”:
- Klient (wymagane, max 60), Model (lista: iPhone 8…iPhone 16 Pro/Max + „Inny”), IMEI/SN (wymagane, 8–20 znaków), Opis usterki (wymagane, max 400), Status (Przyjęte, W trakcie, Gotowe, Wydane), Koszt (liczba ≥ 0), DataPrzyjecia (DatePicker, wymagane), TerminDo (DatePicker, wymagane), DataZakonczenia (opcjonalnie), CzyOplacone (CheckBox).
- „Dodaj” aktywny tylko przy poprawnych danych.
Lista (DataGrid) kolumny:
- Klient, Model, IMEI/SN, Status, Koszt, Data przyjęcia, Termin do, Data zakończenia, Opłacone
Filtry:
- Rok, Miesiąc (1–12), Status (Wszystkie / konkretne)
- zmiana filtrów od razu odświeża widok i „Suma miesiąca”
Akcje:
- Zapisz (JSON), Wczytaj (JSON), Usuń zaznaczone, Oznacz „Gotowe”, Oznacz „Opłacone”
Walidacja „na żywo” (czerwone obramowanie WPF):
- Klient: wymagane, ≤ 60
- Model: wymagany
- IMEI/SN: wymagany, 8–20 znaków
- OpisUsterki: wymagany, ≤ 400
- Koszt: ≥ 0
- DataPrzyjecia i TerminDo: wymagane; TerminDo ≥ DataPrzyjecia
3. Struktura projektu i nazewnictwo
SerwisIphoneWpf
├─ MainWindow.xaml
├─ MainWindow.xaml.cs
├─ Modele
│ └─ dane.cs // ZlecenieSerwisowe + walidacja (IDataErrorInfo)
├─ Walidacja
│ └─ WalidacjaSerwis.cs // RelayCommand + helper walidacji
└─ Logika
└─ LogikaSerwis.cs // kolekcje/binding/filtrowanie/suma/zapis-odczyt
Nowe elementy:
IDataErrorInfo– źródło błędów walidacji dla WPFRelayCommand– komendy do przyciskówICollectionView.Filter– filtrowanie bez zmiany kolekcji
4. Interfejs – rozmieszczenie
Interfejs – opis rozmieszczenia
Główna siatka
4 wiersze: Auto, Auto, *, Auto i 2 kolumny: *, *.
Sekcje: GroupBox „Nowe zlecenie”, pasek filtrów i sumy, DataGrid, pasek akcji.
Sekcja „Nowe zlecenie” (GroupBox)
Grid wewnętrzny 3 wiersze (Auto) × 4 kolumny (2*, 2*, *, *). Pola:
- Klient
TextBlock "Klient"TextBox x:Name="tbKlient"→Text="{Binding Nowe.Klient, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
ToolTip: pierwszy komunikat z(Validation.Errors)[0].ErrorContent - Model
TextBlock "Model"ComboBox x:Name="cbModel"ItemsSource="{Binding Modele}"SelectedItem="{Binding Nowe.Model, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" - IMEI / SN
TextBlock "IMEI / SN"TextBox x:Name="tbImei"→ binding jak wyżej - Koszt (PLN)
TextBlock "Koszt (PLN)"TextBox x:Name="tbKoszt"→Text="{Binding Nowe.Koszt, ...}" - Opis usterki
TextBlock "Opis usterki"TextBox x:Name="tbOpis" AcceptsReturn="True" Height="80"→Text="{Binding Nowe.OpisUsterki, ...}" - Status
TextBlock "Status"ComboBox x:Name="cbStatus"ItemsSource="{Binding Statusy}"SelectedItem="{Binding Nowe.Status, ...}" - Opłacone
CheckBox x:Name="chkOplacone"→IsChecked="{Binding Nowe.CzyOplacone}" - Daty
DatePicker x:Name="dpPrzyjecie"→SelectedDate="{Binding Nowe.DataPrzyjecia, ...}"DatePicker x:Name="dpTermin"→SelectedDate="{Binding Nowe.TerminDo, ...}"DatePicker x:Name="dpZakonczenie"→SelectedDate="{Binding Nowe.DataZakonczenia}"(opcjonalnie)
PrzyciskButton x:Name="btnDodaj" Content="Dodaj"Command="{Binding DodajCmd}"
Aktywność przez RelayCommand.CanExecute (uaktualniane na Nowe.PropertyChanged)
Pasek filtrów i sumyStackPanel (poziomy):
TextBox x:Name="tbRok"→Text="{Binding Rok, UpdateSourceTrigger=PropertyChanged}"TextBox x:Name="tbMiesiac"→Text="{Binding Miesiac, UpdateSourceTrigger=PropertyChanged}"ComboBox x:Name="cbStatusFiltra"→ItemsSource="{Binding StatusFiltra}"SelectedItem="{Binding WybranyStatusFiltra}"TextBlock x:Name="lblSuma"→Text="{Binding SumaMiesiaca, StringFormat={}{0:F2} PLN}"Button x:Name="btnZapisz"→Command="{Binding ZapiszCmd}"Button x:Name="btnWczytaj"→Command="{Binding WczytajCmd}"
Lista zleceńDataGrid x:Name="dgZlecenia"ItemsSource="{Binding WidokZlecen}"SelectedItem="{Binding Zaznaczone}"
Kolumny:
Klient→{Binding Klient}Model→{Binding Model}IMEI/SN→{Binding ImeiSn}Status→{Binding Status}Koszt→{Binding Koszt, StringFormat={}{0:F2}}Przyjęcie→{Binding DataPrzyjecia, StringFormat={}{0:yyyy-MM-dd}}Termin do→{Binding TerminDo, StringFormat={}{0:yyyy-MM-dd}}Zakończenie→{Binding DataZakonczenia, StringFormat={}{0:yyyy-MM-dd}}Opłacone→DataGridCheckBoxColumn{Binding CzyOplacone}
Pasek akcji (dół)
Po prawej:btnUsun → Command="{Binding UsunCmd}"btnGotowe → Command="{Binding OznaczGotoweCmd}"btnOplacone → Command="{Binding OznaczOplaconeCmd}"
Dodatkowe elementy „niewizualne”
MessageBox do komunikatów zapisu/odczytu Globalny styl walidacji dla TextBox, ComboBox, DatePicker (czerwony obrys i tooltip)
ICollectionView.Filter w LogikaSerwis steruje widokiem listy

5. Logika filtrowania i sumy (pseudokod)
Filtr(z):
okRokMies = (Rok==0 || Miesiac==0) ? true
: (z.DataPrzyjecia.Year==Rok || z.DataZakonczenia?.Year==Rok)
&& (z.DataPrzyjecia.Month==Miesiac || z.DataZakonczenia?.Month==Miesiac)
okStatus = (WybranyStatus==Wszystkie) || (z.Status==WybranyStatus)
return okRokMies && okStatus
PrzeliczSume():
suma = 0
dla z w Zlecenia:
jeśli z.DataZakonczenia ma wartość
i z.DataZakonczenia.Year == Rok
i z.DataZakonczenia.Month == Miesiac:
suma += z.Koszt
zwróć suma
6. Kroki wykonania (dla ucznia)
- Utwórz projekt „SerwisIphoneWpf” (.NET 6/8, WPF App).
- Dodaj foldery i pliki jak w pkt 3.
- W
MainWindow.xamlzbuduj layout z bindingami jak niżej. - W
Models/dane.cszdefiniujZlecenieSerwisowe+IDataErrorInfo. - W
Walidacja/WalidacjaSerwis.csdodajRelayCommand. - W
Logika/LogikaSerwis.cszaimplementuj kolekcję, widok, filtry, sumę i komendy. - W
MainWindow.xaml.csustawDataContext = new LogikaSerwis(); - Uruchom i sprawdź: dodawanie, filtry, suma, zapis/odczyt, akcje.
7. Testy (co sprawdzi egzaminator)
- Walidacja blokuje „Dodaj” przy błędach.
- Zmiana Rok/Miesiąc/Status odświeża listę i sumę.
- „Suma miesiąca” liczy tylko zlecenia zakończone w tym miesiącu.
- „Usuń zaznaczone” działa i przelicza sumę.
- Zapis tworzy JSON w AppData, Wczytaj odtwarza stan.
- Oznaczanie „Gotowe” ustawia
DataZakonczenia=Today(jeśli brak). - Oznaczanie „Opłacone” zaznacza
CzyOplacone=true.
8. Kryteria oceniania (30 pkt)
- Model + walidacja + IDataErrorInfo – 6 pkt
- Bindingi (formularz/lista/suma/filtry) – 8 pkt
- Komendy Dodaj/Usuń/Oznacz… – 6 pkt
- Filtr + natychmiastowe odświeżanie + suma – 6 pkt
- Zapis/odczyt JSON + ścieżka AppData – 4 pkt

