Skip to content

Commit 8fb1413

Browse files
committed
recurring events cleanup
1 parent 80fc20f commit 8fb1413

239 files changed

Lines changed: 32681 additions & 20858 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
name: translations
3+
description: Frontend translation workflow using Lingui - extracting, adding, and compiling translations for all supported languages
4+
---
5+
6+
# Frontend Translation Workflow (Lingui)
7+
8+
IMPORTANT: Always update translations as you develop features. When adding new translatable strings, immediately add translations for all supported languages.
9+
10+
## Core Commands
11+
12+
```bash
13+
cd frontend
14+
15+
# Extract translatable strings (use --clean for accurate counts)
16+
yarn messages:extract --clean
17+
18+
# Compile translations for production
19+
yarn messages:compile
20+
21+
# Check for untranslated strings
22+
cd scripts && ./list_untranslated_strings.sh
23+
```
24+
25+
## Process
26+
27+
1. **Extract**: `yarn messages:extract --clean`
28+
2. **Check**: Look at the output table for missing translation counts
29+
3. **Add translations**: Update the `.po` files for each language
30+
4. **Verify**: Run extract again to confirm 0 missing
31+
5. **Compile**: `yarn messages:compile`
32+
33+
## Adding Translations
34+
35+
Add entries to each locale's `.po` file in `frontend/src/locales/`:
36+
37+
```po
38+
#: src/path/to/component.tsx:123
39+
msgid "Your English String"
40+
msgstr "Translated String"
41+
```
42+
43+
## Supported Languages
44+
45+
| Code | Language |
46+
|------|----------|
47+
| en | English (source - no translation needed) |
48+
| de | Deutsch |
49+
| es | Espanol |
50+
| fr | Francais |
51+
| pt | Portugues |
52+
| pt-br | Portugues do Brasil |
53+
| it | Italiano |
54+
| nl | Nederlands |
55+
| zh-cn | Simplified Chinese |
56+
| zh-hk | Traditional Chinese (HK) |
57+
| vi | Tieng Viet |
58+
| ru | Russian (currently untranslated) |
59+
60+
## Troubleshooting
61+
62+
- **Counts seem wrong**: Use `--clean` flag to remove obsolete entries
63+
- **Translation not appearing**: Run `yarn messages:compile` after adding
64+
- **Syntax errors**: Check for proper escaping of quotes in `.po` files
Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1 @@
1-
---
2-
name: translations
3-
description: Frontend translation workflow using Lingui - extracting, adding, and compiling translations for all supported languages
4-
---
5-
6-
# Frontend Translation Workflow (Lingui)
7-
8-
IMPORTANT: Always update translations as you develop features. When adding new translatable strings, immediately add translations for all supported languages.
9-
10-
## Core Commands
11-
12-
```bash
13-
cd frontend
14-
15-
# Extract translatable strings (use --clean for accurate counts)
16-
yarn messages:extract --clean
17-
18-
# Compile translations for production
19-
yarn messages:compile
20-
21-
# Check for untranslated strings
22-
cd scripts && ./list_untranslated_strings.sh
23-
```
24-
25-
## Process
26-
27-
1. **Extract**: `yarn messages:extract --clean`
28-
2. **Check**: Look at the output table for missing translation counts
29-
3. **Add translations**: Update the `.po` files for each language
30-
4. **Verify**: Run extract again to confirm 0 missing
31-
5. **Compile**: `yarn messages:compile`
32-
33-
## Adding Translations
34-
35-
Add entries to each locale's `.po` file in `frontend/src/locales/`:
36-
37-
```po
38-
#: src/path/to/component.tsx:123
39-
msgid "Your English String"
40-
msgstr "Translated String"
41-
```
42-
43-
## Supported Languages
44-
45-
| Code | Language |
46-
|------|----------|
47-
| en | English (source - no translation needed) |
48-
| de | Deutsch |
49-
| es | Espanol |
50-
| fr | Francais |
51-
| pt | Portugues |
52-
| pt-br | Portugues do Brasil |
53-
| it | Italiano |
54-
| nl | Nederlands |
55-
| zh-cn | Simplified Chinese |
56-
| zh-hk | Traditional Chinese (HK) |
57-
| vi | Tieng Viet |
58-
| ru | Russian (currently untranslated) |
59-
60-
## Troubleshooting
61-
62-
- **Counts seem wrong**: Use `--clean` flag to remove obsolete entries
63-
- **Translation not appearing**: Run `yarn messages:compile` after adding
64-
- **Syntax errors**: Check for proper escaping of quotes in `.po` files
1+
see @../../../.agents/skills/translations/SKILL.md

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ prompts/
2020

2121
/plans/**
2222
/plans
23+
24+
.claude/worktrees/

backend/app/Console/Kernel.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,27 @@
66
use HiEvents\Jobs\Waitlist\ProcessExpiredWaitlistOffersJob;
77
use Illuminate\Console\Scheduling\Schedule;
88
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
9+
use Illuminate\Support\Facades\DB;
10+
use Illuminate\Support\Facades\Log;
911

1012
class Kernel extends ConsoleKernel
1113
{
1214
protected function schedule(Schedule $schedule): void
1315
{
1416
$schedule->job(new SendScheduledMessagesJob)->everyMinute()->withoutOverlapping();
1517
$schedule->job(new ProcessExpiredWaitlistOffersJob)->everyMinute()->withoutOverlapping();
18+
19+
$schedule->call(function (): void {
20+
$count = DB::table('failed_jobs')->count();
21+
if ($count > 0) {
22+
Log::warning('Failed jobs present in queue', ['count' => $count]);
23+
}
24+
})->everyFiveMinutes()->name('failed-jobs-monitor')->withoutOverlapping();
1625
}
1726

1827
protected function commands(): void
1928
{
20-
$this->load(__DIR__ . '/Commands');
29+
$this->load(__DIR__.'/Commands');
2130

2231
include base_path('routes/console.php');
2332
}

backend/app/DomainObjects/CheckInListDomainObject.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
use HiEvents\DomainObjects\SortingAndFiltering\AllowedSorts;
88
use Illuminate\Support\Collection;
99

10+
/**
11+
* A `null` event_occurrence_id means the list applies to every occurrence of the
12+
* event (the default for recurring events and the only meaningful value for
13+
* single-occurrence events). A non-null value scopes the list to that one
14+
* occurrence — only attendees on that occurrence can be checked in via the list.
15+
*/
1016
class CheckInListDomainObject extends Generated\CheckInListDomainObjectAbstract implements IsSortable
1117
{
1218
private ?Collection $products = null;

backend/app/DomainObjects/Enums/EventCategory.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@ enum EventCategory: string
88

99
// Community
1010
case SOCIAL = 'SOCIAL';
11+
case FAMILY = 'FAMILY';
12+
case HOBBIES = 'HOBBIES';
1113
case FOOD_DRINK = 'FOOD_DRINK';
14+
case WELLNESS = 'WELLNESS';
15+
case SPIRITUALITY = 'SPIRITUALITY';
16+
case OUTDOORS = 'OUTDOORS';
17+
case TOURS = 'TOURS';
1218
case CHARITY = 'CHARITY';
1319

1420
// Creative & Culture
1521
case MUSIC = 'MUSIC';
1622
case ART = 'ART';
1723
case COMEDY = 'COMEDY';
1824
case THEATER = 'THEATER';
25+
case FILM = 'FILM';
26+
case DANCE = 'DANCE';
1927

2028
// Professional & Learning
2129
case BUSINESS = 'BUSINESS';
@@ -26,6 +34,7 @@ enum EventCategory: string
2634
// Leisure & Nightlife
2735
case SPORTS = 'SPORTS';
2836
case FESTIVAL = 'FESTIVAL';
37+
case SEASONAL = 'SEASONAL';
2938
case NIGHTLIFE = 'NIGHTLIFE';
3039

3140
// Catch-all
@@ -35,18 +44,27 @@ public function label(): string
3544
{
3645
return match ($this) {
3746
self::SOCIAL => __('Social'),
47+
self::FAMILY => __('Family'),
48+
self::HOBBIES => __('Hobbies'),
3849
self::FOOD_DRINK => __('Food & Drink'),
50+
self::WELLNESS => __('Wellness'),
51+
self::SPIRITUALITY => __('Spirituality'),
52+
self::OUTDOORS => __('Outdoors'),
53+
self::TOURS => __('Tours'),
3954
self::CHARITY => __('Charity'),
4055
self::MUSIC => __('Music'),
4156
self::ART => __('Art'),
4257
self::COMEDY => __('Comedy'),
4358
self::THEATER => __('Theater'),
59+
self::FILM => __('Film'),
60+
self::DANCE => __('Dance'),
4461
self::BUSINESS => __('Business'),
4562
self::TECH => __('Tech'),
4663
self::EDUCATION => __('Education'),
4764
self::WORKSHOP => __('Workshop'),
4865
self::SPORTS => __('Sports'),
4966
self::FESTIVAL => __('Festival'),
67+
self::SEASONAL => __('Seasonal'),
5068
self::NIGHTLIFE => __('Nightlife'),
5169
self::OTHER => __('Other'),
5270
};
@@ -56,20 +74,29 @@ public function emoji(): string
5674
{
5775
return match ($this) {
5876
self::SOCIAL => '🤝',
77+
self::FAMILY => '👨‍👩‍👧‍👦',
78+
self::HOBBIES => '🧩',
5979
self::FOOD_DRINK => '🍽️',
80+
self::WELLNESS => '🧘',
81+
self::SPIRITUALITY => '🙏',
82+
self::OUTDOORS => '🏞️',
83+
self::TOURS => '🗺️',
6084
self::CHARITY => '🎗️',
6185
self::MUSIC => '🎵',
6286
self::ART => '🎨',
6387
self::COMEDY => '😂',
6488
self::THEATER => '🎭',
89+
self::FILM => '🎬',
90+
self::DANCE => '💃',
6591
self::BUSINESS => '💼',
6692
self::TECH => '💻',
6793
self::EDUCATION => '📚',
6894
self::WORKSHOP => '🛠️',
6995
self::SPORTS => '',
70-
self::FESTIVAL => '🎉',
96+
self::FESTIVAL => '🎪',
97+
self::SEASONAL => '🎊',
7198
self::NIGHTLIFE => '🪩',
72-
self::OTHER => '📝',
99+
self::OTHER => '🤔',
73100
};
74101
}
75102
}

backend/app/DomainObjects/Enums/OrderAuditAction.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ enum OrderAuditAction: string
1010
case ORDER_UPDATED = 'ORDER_UPDATED';
1111
case ATTENDEE_EMAIL_RESENT = 'ATTENDEE_EMAIL_RESENT';
1212
case ORDER_EMAIL_RESENT = 'ORDER_EMAIL_RESENT';
13+
case AUTOMATIC_REFUND_SKIPPED = 'AUTOMATIC_REFUND_SKIPPED';
14+
case AUTOMATIC_REFUND_FAILED = 'AUTOMATIC_REFUND_FAILED';
15+
case MANUAL_ATTENDEE_CAPACITY_OVERRIDE = 'MANUAL_ATTENDEE_CAPACITY_OVERRIDE';
1316
}

backend/app/DomainObjects/Generated/ProductPriceOccurrenceOverrideDomainObjectAbstract.php

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@ abstract class ProductPriceOccurrenceOverrideDomainObjectAbstract extends \HiEve
1616
final public const PRICE = 'price';
1717
final public const CREATED_AT = 'created_at';
1818
final public const UPDATED_AT = 'updated_at';
19-
final public const QUANTITY_AVAILABLE = 'quantity_available';
2019

2120
protected int $id;
2221
protected int $event_occurrence_id;
2322
protected int $product_price_id;
2423
protected float $price;
2524
protected ?string $created_at = null;
2625
protected ?string $updated_at = null;
27-
protected ?int $quantity_available = null;
2826

2927
public function toArray(): array
3028
{
@@ -35,7 +33,6 @@ public function toArray(): array
3533
'price' => $this->price ?? null,
3634
'created_at' => $this->created_at ?? null,
3735
'updated_at' => $this->updated_at ?? null,
38-
'quantity_available' => $this->quantity_available ?? null,
3936
];
4037
}
4138

@@ -104,15 +101,4 @@ public function getUpdatedAt(): ?string
104101
{
105102
return $this->updated_at;
106103
}
107-
108-
public function setQuantityAvailable(?int $quantity_available): self
109-
{
110-
$this->quantity_available = $quantity_available;
111-
return $this;
112-
}
113-
114-
public function getQuantityAvailable(): ?int
115-
{
116-
return $this->quantity_available;
117-
}
118104
}

backend/app/DomainObjects/Generated/WaitlistEntryDomainObjectAbstract.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ abstract class WaitlistEntryDomainObjectAbstract extends \HiEvents\DomainObjects
1414
final public const EVENT_ID = 'event_id';
1515
final public const PRODUCT_PRICE_ID = 'product_price_id';
1616
final public const ORDER_ID = 'order_id';
17+
final public const EVENT_OCCURRENCE_ID = 'event_occurrence_id';
1718
final public const EMAIL = 'email';
1819
final public const FIRST_NAME = 'first_name';
1920
final public const LAST_NAME = 'last_name';
@@ -34,6 +35,7 @@ abstract class WaitlistEntryDomainObjectAbstract extends \HiEvents\DomainObjects
3435
protected int $event_id;
3536
protected int $product_price_id;
3637
protected ?int $order_id = null;
38+
protected ?int $event_occurrence_id = null;
3739
protected string $email;
3840
protected string $first_name;
3941
protected ?string $last_name = null;
@@ -57,6 +59,7 @@ public function toArray(): array
5759
'event_id' => $this->event_id ?? null,
5860
'product_price_id' => $this->product_price_id ?? null,
5961
'order_id' => $this->order_id ?? null,
62+
'event_occurrence_id' => $this->event_occurrence_id ?? null,
6063
'email' => $this->email ?? null,
6164
'first_name' => $this->first_name ?? null,
6265
'last_name' => $this->last_name ?? null,
@@ -119,6 +122,17 @@ public function getOrderId(): ?int
119122
return $this->order_id;
120123
}
121124

125+
public function setEventOccurrenceId(?int $event_occurrence_id): self
126+
{
127+
$this->event_occurrence_id = $event_occurrence_id;
128+
return $this;
129+
}
130+
131+
public function getEventOccurrenceId(): ?int
132+
{
133+
return $this->event_occurrence_id;
134+
}
135+
122136
public function setEmail(string $email): self
123137
{
124138
$this->email = $email;

0 commit comments

Comments
 (0)