Plan: ein Streifen im Dashboard zeigt die Restfrist
Vom Betreiber gefordert, und der Ort stimmt: eine Mail sieben Tage vorher kann im Postfach untergehen, die eigene Uebersicht oeffnet der Kunde ohnehin. Er nennt, wie lange der ZUGANG noch steht — nicht, wann etwas geloescht wird. Das ist die Frist, die den Kunden betrifft. Und er ist der natuerliche Platz fuer die Export-Antwort: wer liest, dass die Zeit laeuft, will es sich im selben Atemzug anders ueberlegen koennen.claude/nice-moser-521659
parent
34ef35518c
commit
82ace84d01
|
|
@ -414,6 +414,131 @@ it('laesst sie nach dem Laufzeitende nicht mehr aendern', function () {
|
|||
|
||||
---
|
||||
|
||||
## Task 5: Der Streifen im Dashboard, der die Frist zeigt
|
||||
|
||||
**Files:**
|
||||
- Modify: `app/Livewire/Dashboard.php`
|
||||
- Modify: `resources/views/livewire/dashboard.blade.php`
|
||||
- Modify: `lang/{de,en}/dashboard.php`
|
||||
- Test: `tests/Feature/Cancellation/DashboardCountdownTest.php`
|
||||
|
||||
**Vom Betreiber gefordert, und es ist der richtige Ort:** das Dashboard ist die
|
||||
Seite, die ein Kunde ohnehin öffnet. Eine Mail sieben Tage vorher kann im
|
||||
Postfach untergehen; ein Streifen über der eigenen Übersicht nicht.
|
||||
|
||||
Er zeigt, **wie lange der Zugang noch steht** — nicht, wann irgendetwas
|
||||
gelöscht wird. Das ist die Frist, die den Kunden betrifft: ab dem Laufzeitende
|
||||
kommt er nicht mehr an seine Cloud.
|
||||
|
||||
Und er ist der natürliche Platz für Aufgabe 4: wer hier liest, dass die Zeit
|
||||
läuft, will im selben Atemzug seine Antwort zum Export ändern können.
|
||||
|
||||
- [ ] **Schritt 1: Die fehlschlagenden Prüfungen schreiben**
|
||||
|
||||
```php
|
||||
<?php // tests/Feature/Cancellation/DashboardCountdownTest.php
|
||||
|
||||
use App\Livewire\Dashboard;
|
||||
use Livewire\Livewire;
|
||||
|
||||
it('zeigt nach einer Kuendigung, wie lange der Zugang noch steht', function () {
|
||||
[$user, $instance] = gekuendigteInstanz(endetIn: now()->addDays(12));
|
||||
|
||||
Livewire::actingAs($user)->test(Dashboard::class)
|
||||
->assertSee(__('dashboard.ending.title'))
|
||||
->assertSee($instance->service_ends_at->local()->isoFormat('LL'));
|
||||
});
|
||||
|
||||
it('zeigt den Streifen nicht, solange nicht gekuendigt wurde', function () {
|
||||
[$user] = laufendeInstanz();
|
||||
|
||||
Livewire::actingAs($user)->test(Dashboard::class)
|
||||
->assertDontSee(__('dashboard.ending.title'));
|
||||
});
|
||||
|
||||
it('zeigt ihn auch nach dem Laufzeitende nicht mehr', function () {
|
||||
// Danach ist der Zugang zu, und ein Streifen, der eine Restzeit nennt,
|
||||
// waere schlicht falsch. Was dann gilt, sagt die Seite an anderer Stelle.
|
||||
[$user] = gekuendigteInstanz(endetIn: now()->subDay(), status: 'ended');
|
||||
|
||||
Livewire::actingAs($user)->test(Dashboard::class)
|
||||
->assertDontSee(__('dashboard.ending.title'));
|
||||
});
|
||||
|
||||
it('nennt keine Restzeit, die schon abgelaufen ist', function () {
|
||||
// Der Fall zwischen den Stuehlen: das Laufzeitende ist vorbei, aber der
|
||||
// stuendliche Lauf hat die Instanz noch nicht auf `ended` gestellt. Eine
|
||||
// Zeile "noch -3 Stunden" ist die Sorte Fehler, die niemand meldet und
|
||||
// jeder sieht.
|
||||
[$user] = gekuendigteInstanz(endetIn: now()->subHours(3));
|
||||
|
||||
$html = Livewire::actingAs($user)->test(Dashboard::class)->html();
|
||||
|
||||
expect($html)->not->toContain('-'); // an der Restzeit, nicht im ganzen Dokument — siehe unten
|
||||
});
|
||||
|
||||
it('traegt die Antwort zum Export und laesst sie aendern', function () {
|
||||
[$user, $instance] = gekuendigteInstanz(endetIn: now()->addDays(12));
|
||||
$instance->update(['export_wish' => false]);
|
||||
|
||||
Livewire::actingAs($user)->test(Dashboard::class)
|
||||
->assertSee(__('dashboard.ending.export_no'))
|
||||
->call('setExportWish', true);
|
||||
|
||||
expect($instance->fresh()->export_wish)->toBeTrue();
|
||||
});
|
||||
```
|
||||
|
||||
**Zur vierten Prüfung:** `not->toContain('-')` über das ganze Dokument trägt
|
||||
nicht — ein Datum enthält Bindestriche, eine CSS-Klasse auch. Schreib sie so,
|
||||
dass sie **die Restzeit** prüft und nicht die Seite: entweder gegen den Wert,
|
||||
den die Komponente berechnet, oder gegen den Textbaustein mit eingesetzter
|
||||
Zahl. Eine Zusicherung, die aus dem falschen Grund grün ist, ist keine.
|
||||
|
||||
- [ ] **Schritt 2: Laufen lassen, Fehlschlag bestätigen**
|
||||
|
||||
- [ ] **Schritt 3: Den Streifen bauen**
|
||||
|
||||
`Dashboard::render()` holt die Instanz bereits (Zeile 36 ff.) — von dort kommt
|
||||
`service_ends_at`. Der Streifen erscheint, wenn `status === 'cancellation_scheduled'`
|
||||
**und** das Ende in der Zukunft liegt.
|
||||
|
||||
Die Restzeit geht durch `->local()` (R19) und wird **abgerundet auf ganze Tage
|
||||
genannt, solange mehr als ein Tag bleibt** — „noch 12 Tage" liest sich, „noch
|
||||
11 Tage 7 Stunden" nicht. Am letzten Tag zählt er Stunden; das ist der Moment,
|
||||
in dem die Zahl wirklich zählt.
|
||||
|
||||
Der Streifen benutzt dieselbe Warnfarbe wie der bestehende Zugangsdaten-Kasten
|
||||
darüber (`border-warning-border bg-warning-bg text-warning`) und steht an
|
||||
derselben Stelle im Fluss — nicht zwei verschiedene Sprachen für zwei
|
||||
verschiedene Dringlichkeiten auf einer Seite.
|
||||
|
||||
Er nennt drei Dinge: das Datum, die Restzeit, und **was dann geschieht** — dass
|
||||
der Zugang zur Cloud endet und ein Selbst-Herunterladen bis dahin möglich ist.
|
||||
Dazu die Antwort zum Export mit einem Schalter, sie zu ändern (Aufgabe 4).
|
||||
|
||||
- [ ] **Schritt 4: Laufen lassen, grün**
|
||||
|
||||
- [ ] **Schritt 5: Ganze Suite**
|
||||
|
||||
- [ ] **Schritt 6: Festschreiben**
|
||||
|
||||
```bash
|
||||
git commit -F- <<'MSG'
|
||||
Ein Streifen im Dashboard sagt, wie lange der Zugang noch steht
|
||||
|
||||
Eine Mail sieben Tage vorher kann im Postfach untergehen; die eigene Uebersicht
|
||||
oeffnet der Kunde ohnehin. Der Streifen nennt das Datum, die Restzeit und was
|
||||
danach geschieht — dass der Zugang zur Cloud endet, nicht dass irgendetwas
|
||||
geloescht wird. Das ist die Frist, die ihn betrifft.
|
||||
|
||||
Und er traegt die Antwort zum Export: wer liest, dass die Zeit laeuft, will es
|
||||
sich im selben Atemzug anders ueberlegen koennen.
|
||||
MSG
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Selbstdurchsicht
|
||||
|
||||
**Abdeckung von Teil A des Entwurfs**
|
||||
|
|
@ -422,8 +547,9 @@ it('laesst sie nach dem Laufzeitende nicht mehr aendern', function () {
|
|||
|---|---|
|
||||
| Beim Kündigen wird gefragt | 2 |
|
||||
| Drei Zustände, `null` ≠ „nein" | 1 |
|
||||
| Antwort später änderbar | 4 |
|
||||
| Antwort später änderbar | 4, 5 |
|
||||
| Erinnerung vor dem Laufzeitende | 3 |
|
||||
| Streifen im Dashboard mit der Restfrist | 5 |
|
||||
| Kein Gast angefasst, kein Speicher gebraucht | alle |
|
||||
|
||||
**Was Teil A ausdrücklich NICHT tut**
|
||||
|
|
|
|||
Loading…
Reference in New Issue