Compare commits

...

13 Commits

Author SHA1 Message Date
7c1125e213 Small improvements 2026-04-30 20:39:56 +02:00
b91af2e889 Small improvements 2026-04-30 20:30:00 +02:00
4a97cf230b Bugfixes 2026-04-29 22:34:40 +02:00
0c7e3ab365 Bugfixes 2026-04-29 22:26:56 +02:00
222113b0d5 Bugfixes 2026-04-29 21:53:19 +02:00
895e44c984 Merge remote-tracking branch 'origin/main' 2026-04-29 21:51:02 +02:00
ef3d03200e Bugfixes 2026-04-29 21:50:05 +02:00
tux
6c891ff64a set prod user 2026-04-29 20:07:10 +02:00
d9ba5ab4f1 Merge remote-tracking branch 'origin/main' 2026-04-29 19:43:58 +02:00
1816ca5165 Bugfixes 2026-04-29 19:43:45 +02:00
tux
dff7d65476 production deployment stuff 2026-04-29 19:35:11 +02:00
ce57669263 Bugfixes 2026-04-29 18:23:28 +02:00
tux
2444aab204 prod docker stuff 2026-04-26 17:46:21 +02:00
16 changed files with 131 additions and 18 deletions

5
.dockerignore Normal file
View File

@@ -0,0 +1,5 @@
.ai
.junie
.git
storage
tests

View File

@@ -19,7 +19,7 @@ class SignUpRequest {
public Tenant $localGroup,
public DateTime $birthday,
public string $address_1,
public string $address_2,
public ?string $address_2,
public string $postcode,
public string $city,
public string $email_1,

View File

@@ -41,7 +41,8 @@ class CreateController extends CommonController {
$payPerDay = $request->input('eventPayPerDay');
$payDirect = $request->input('eventPayDirectly');
$billingDeadline = $eventEnd->modify('+1 month');
$billingDeadline = clone $eventEnd;
$billingDeadline->modify('+6 weeks');
$createRequest = new CreateEventRequest(
$request->input('eventName'),

View File

@@ -97,7 +97,8 @@ class SignupController extends CommonController {
);
$signupRequest = new SignUpRequest(
$event,$registrationData['userId'],
$event,
$registrationData['userId'] ?? null,
$registrationData['vorname'],
$registrationData['nachname'],
$registrationData['pfadiname'],

View File

@@ -16,10 +16,13 @@ Route::middleware(IdentifyTenant::class)->group(function () {
Route::get('/{eventId}/signup', SignupController::class);
Route::middleware(['auth'])->group(function () {
Route::get('/new', CreateController::class);
Route::get('/details/{eventId}', DetailsController::class);
Route::get('/details/{eventId}/pdf/{listType}', [DetailsController::class, 'downloadPdfList']);
Route::get('/details/{eventId}/csv/{listType}', [DetailsController::class, 'downloadCsvList']);
});
});
Route::middleware(['auth'])->group(function () {
Route::get('/create-event', CreateController::class);
});
});

View File

@@ -1,5 +1,6 @@
<script setup>
import {reactive} from "vue";
import ErrorText from "../../../../../../Views/Components/ErrorText.vue";
const props = defineProps({ formData: Object, localGroups: Array })
const emit = defineEmits(['next', 'back'])
@@ -64,6 +65,11 @@ const next = () => {
hasError = true
}
if (!props.formData.telefon_1) {
errors.telefon_1 = 'Bitte eine Telefonnummer angeben.'
hasError = true
}
if (!props.formData.email_1) {
errors.email_1 = 'Bitte eine E-Mail-Adresse angeben.'
hasError = true
@@ -80,8 +86,8 @@ const next = () => {
<div>
<h3>Persönliche Daten</h3>
<table class="form-table">
<tr><td>Vorname:</td><td><input type="text" v-model="props.formData.vorname" /></td></tr>
<tr><td>Nachname:</td><td><input type="text" v-model="props.formData.nachname" /></td></tr>
<tr><td>Vorname:</td><td><input type="text" v-model="props.formData.vorname" /><ErrorText :message="errors.vorname"/></td></tr>
<tr><td>Nachname:</td><td><input type="text" v-model="props.formData.nachname" /><ErrorText :message="errors.nachname"/></td></tr>
<tr><td>Pfadiname:</td><td><input type="text" v-model="props.formData.pfadiname" /></td></tr>
<tr>
<td>Stamm:</td>
@@ -90,9 +96,10 @@ const next = () => {
<option value="-1">Bitte wählen</option>
<option v-for="lg in localGroups" :key="lg.id" :value="lg.id">{{ lg.name }}</option>
</select>
<ErrorText :message="errors.localGroup" />
</td>
</tr>
<tr><td>Geburtsdatum:</td><td><input type="date" v-model="props.formData.geburtsdatum" /></td></tr>
<tr><td>Geburtsdatum:</td><td><input type="date" v-model="props.formData.geburtsdatum" /><ErrorText :message="errors.geburtsdatum" /></td></tr>
<tr>
<td>Adresse:</td>
<td>
@@ -103,6 +110,7 @@ const next = () => {
<td></td>
<td>
<input type="text" v-model="props.formData.address2" />
<ErrorText :message="errors.address1" />
</td>
</tr>
<tr>
@@ -110,10 +118,12 @@ const next = () => {
<td>
<input maxlength="5" type="text" v-model="props.formData.plz" style="width: 100px; margin-right: 8px;" />
<input type="text" v-model="props.formData.ort" style="width: calc(100% - 110px);" />
<ErrorText :message="errors.plz" />
<ErrorText :message="errors.ort" />
</td>
</tr>
<tr><td>Telefon:</td><td><input type="text" v-model="props.formData.telefon_1" /></td></tr>
<tr><td>E-Mail:</td><td><input type="text" v-model="props.formData.email_1" /></td></tr>
<tr><td>Telefon:</td><td><input type="text" v-model="props.formData.telefon_1" /><ErrorText :message="errors.telefon_1" /></td></tr>
<tr><td>E-Mail:</td><td><input type="text" v-model="props.formData.email_1" /><ErrorText :message="errors.email_1" /></td></tr>
<tr>
<td colspan="2" class="btn-row">
<button type="button" class="btn-primary" @click="next">Weiter </button>

View File

@@ -118,7 +118,7 @@ async function sendData() {
name="contact_telephone" v-model="userTelephone"
style="font-size: 14pt; width: 550px;" /><br /><br />
<span id="decision" v-if="userEmail !== '' && decision === ''">
<span id="decision" v-if="userEmail !== '' && userTelephone !== '' && decision === ''">
<label><br />
<strong>Möchtest du den Betrag spenden?</strong>
</label><br />

View File

@@ -37,7 +37,7 @@ class UserRegistrationCommand {
return $response;
}
$generateActivationCoedeRequest = new GenerateActivationTokenRequest($user);
$generateActivationCoedeRequest = new GenerateActivationTokenRequest($user, new \DateTime()->add(new \DateInterval('P1D')));
$generateActivationCoedeDommand = new GenerateActivationTokenCommand($generateActivationCoedeRequest);
$result = $generateActivationCoedeDommand->execute();

View File

@@ -17,7 +17,8 @@ class activationCodeTemplate extends MessageTemplate {
}
public function composeMessage(EmailAddress $emailAddress, string $activationCode): void {
$this->message = "Dein Aktivierungscode lautet: {$activationCode}" . PHP_EOL .
"Gib diesen zusammen mit der Mailadresse {$emailAddress->getValue()} ein.";
$this->message = "Hallo,<br >dein angefordertet Aktivierungscode lautet: {$activationCode}<br />.
Gib diesen zusammen mit der Mailadresse {$emailAddress->getValue()} ein.<br /><br />
Hast du keinen Code angefordert?<br />In diesem Fall kannst du die E-Mail ignorieren.";
}
}

View File

@@ -129,7 +129,7 @@ class GlobalDataProvider {
$navigation['events'][] = ['url' => '/event/details/' . $event->identifier, 'display' => $event->name];
}
$navigation['events'][] = ['url' => '/event/new', 'display' => 'Neue Veranstaltung'];
$navigation['events'][] = ['url' => '/create-event', 'display' => 'Neue Veranstaltung'];
}
}

View File

@@ -90,7 +90,7 @@ class CostUnitRepository {
$visibleCostUnits = [];
/** @var CostUnit $costUnit */
foreach (Costunit::where($criteria)->get() as $costUnit) {
if ($costUnit->treasurers()->where('user_id', $user->id)->exists() || $canSeeAll || $disableAccessCheck) {
if ($canSeeAll || $disableAccessCheck || $costUnit->treasurers()->where('user_id', $user->id)->exists() ) {
if ($forDisplay) {
$visibleCostUnits[] = new CostUnitResource($costUnit)->toArray(request());
} else {

View File

@@ -42,7 +42,7 @@ return new class extends Migration {
$table->foreignId('cost_unit_id')->nullable()->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate();
$table->string('name');
$table->string('identifier');
$table->string('identifier')->unique();
$table->string('location');
$table->string('postal_code');
$table->string('email');

View File

@@ -22,7 +22,7 @@ return new class extends Migration {
$table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate();
$table->foreignId('user_id')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate();
$table->string('identifier');
$table->string('identifier')->unique();
$table->string('firstname');
$table->string('lastname');
$table->string('nickname')->nullable();
@@ -63,7 +63,7 @@ return new class extends Migration {
$table->dateTime('unregistered_at')->nullable();
$table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->restrictOnDelete()->cascadeOnUpdate();
$table->foreign('eating_habits')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate();
$table->foreign('eating_habit')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate();
$table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->restrictOnDelete()->cascadeOnUpdate();
$table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate();
$table->foreign('local_group')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate();

14
docker-compose.prod Normal file
View File

@@ -0,0 +1,14 @@
services:
mareike-app:
build:
context: .
dockerfile: docker/prod.Dockerfile
mareike-nginx:
build:
context: .
dockerfile: docker/Dockerfile.nginx
depends_on:
- mareike-app
ports:
- 9000:80

43
docker/prod.Dockerfile Normal file
View File

@@ -0,0 +1,43 @@
FROM php:8.5-fpm-alpine AS base
ARG UID=1000
ARG GID=1000
ENV USER=mareike
ENV GROUPNAME=$USER
RUN addgroup -g ${GID} -S ${GROUPNAME} \
&& adduser -u ${UID} -D -S -G ${GROUPNAME} ${USER}
RUN apk add --no-cache \
mc \
unzip \
rsync
COPY --chmod=0755 /docker/php/composer.phar /usr/bin/composer
RUN apk add --no-cache --virtual .build-deps \
autoconf \
build-base \
libzip-dev \
libpng-dev \
libxml2-dev \
oniguruma-dev \
nodejs \
imagemagick-dev \
npm && \
pecl install imagick && docker-php-ext-enable imagick
RUN docker-php-ext-install mysqli pdo pdo_mysql mbstring zip exif pcntl gd
COPY . /var/www/html
WORKDIR /var/www/html
RUN composer install --no-dev --optimize-autoloader
RUN npm install
RUN npm run build
EXPOSE 9000
RUN mv /var/www/html /src
COPY docker/run-mareike.sh /usr/local/bin/
USER mareike
CMD ["run-mareike.sh"]

35
docker/run-mareike.sh Normal file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
set -e
rsync -rlDog --chown $USER:$GROUPNAME --delete --exclude=/storage /src/ /var/www/html
install -d -m 0755 -o $USER -g $GROUPNAME \
storage \
storage/framework \
storage/framework/cache \
storage/framework/sessions \
storage/framework/views \
storage/app \
storage/app/private \
storage/logs
rm .dockerignore
rm .editorconfig
rm .env.example
rm .gitattributes
rm .gitignore
rm Makefile
rm README.md
rm docker-compose.dev
rm docker-compose.prod
rm justfile
rm phpunit.xml
rm -rf node_modules
rm composer.json
rm composer.lock
rm package-lock.json
rm package.json
rm -rf docker
php artisan migrate --force
exec "php-fpm"