Migrate omsorgapp to browser SPA, add Docker/CI build setup
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 3s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Failing after 4s
Docker-Images bauen und veröffentlichen / build (VITE_OMSORG_CORE_URL=${{ vars.OMSORG_CORE_PUBLIC_URL }}, omsorgapp/Dockerfile, omsorgapp) (push) Successful in 3s
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 3s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Failing after 4s
Docker-Images bauen und veröffentlichen / build (VITE_OMSORG_CORE_URL=${{ vars.OMSORG_CORE_PUBLIC_URL }}, omsorgapp/Dockerfile, omsorgapp) (push) Successful in 3s
- omsorgapp: drop Electron, run as a plain Vite/React browser app; refresh token moves to an HttpOnly cookie (omsorgCore), CORS added for the new browser origin, document download/preview switched to Blob-based browser APIs. - Add Dockerfiles for omsorgCore, omsorgapp, and omsorgWeb, a docker-compose.yml wiring Postgres/MySQL/all three apps together, and a Gitea Actions workflow that builds and pushes images to the repo's container registry on push to main and on version tags. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
e9e96a57dc
commit
598dfcd38a
@@ -0,0 +1,159 @@
|
||||
import OmsorgButton from "../../components/ui/OmsorgButton";
|
||||
import { useValueListItems } from "../../app/useValueListItems";
|
||||
|
||||
export const emptyContractForm = {
|
||||
contractType: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
status: "",
|
||||
weeklyHours: "",
|
||||
hourlyWage: "",
|
||||
allowancesDescription: "",
|
||||
overtimeRules: "",
|
||||
vacationDaysPerYear: "",
|
||||
probationPeriodMonths: "",
|
||||
};
|
||||
|
||||
export function contractToFormValues(contract) {
|
||||
return {
|
||||
contractType: contract.contractType ?? "",
|
||||
startDate: contract.startDate ?? "",
|
||||
endDate: contract.endDate ?? "",
|
||||
status: contract.status ?? "",
|
||||
weeklyHours: contract.weeklyHours ?? "",
|
||||
hourlyWage: contract.hourlyWage ?? "",
|
||||
allowancesDescription: contract.allowancesDescription ?? "",
|
||||
overtimeRules: contract.overtimeRules ?? "",
|
||||
vacationDaysPerYear: contract.vacationDaysPerYear ?? "",
|
||||
probationPeriodMonths: contract.probationPeriodMonths ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
export function contractFormToPayload(form, { employeeId, includeStatus = false } = {}) {
|
||||
const payload = {
|
||||
contractType: form.contractType,
|
||||
employeeId,
|
||||
facilityId: null,
|
||||
startDate: form.startDate,
|
||||
endDate: form.endDate || null,
|
||||
weeklyHours: form.weeklyHours === "" ? null : Number(form.weeklyHours),
|
||||
hourlyWage: form.hourlyWage === "" ? null : Number(form.hourlyWage),
|
||||
allowancesDescription: form.allowancesDescription.trim() || null,
|
||||
overtimeRules: form.overtimeRules.trim() || null,
|
||||
vacationDaysPerYear: form.vacationDaysPerYear === "" ? null : Number(form.vacationDaysPerYear),
|
||||
probationPeriodMonths: form.probationPeriodMonths === "" ? null : Number(form.probationPeriodMonths),
|
||||
};
|
||||
|
||||
if (includeStatus) {
|
||||
payload.status = form.status;
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
export default function ContractForm({ form, onChange, includeStatus = false }) {
|
||||
const { items: contractTypes } = useValueListItems("ContractType");
|
||||
const { items: contractStatuses } = useValueListItems("ContractStatus");
|
||||
|
||||
function updateField(field) {
|
||||
return (event) => onChange({ ...form, [field]: event.target.value });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="form-grid">
|
||||
<label className="form-field">
|
||||
<span>Vertragstyp *</span>
|
||||
<select value={form.contractType} onChange={updateField("contractType")} required>
|
||||
<option value="">— auswählen —</option>
|
||||
{contractTypes.map((option) => (
|
||||
<option key={option.id} value={option.value}>
|
||||
{option.value}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
{includeStatus && (
|
||||
<label className="form-field">
|
||||
<span>Status</span>
|
||||
<select value={form.status} onChange={updateField("status")}>
|
||||
{contractStatuses.map((option) => (
|
||||
<option key={option.id} value={option.value}>
|
||||
{option.value}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
)}
|
||||
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Beginn *</span>
|
||||
<input type="date" value={form.startDate} onChange={updateField("startDate")} required />
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Ende</span>
|
||||
<input type="date" value={form.endDate} onChange={updateField("endDate")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Arbeitszeit (Std./Woche)</span>
|
||||
<input type="number" min="0" step="0.5" value={form.weeklyHours} onChange={updateField("weeklyHours")} />
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Stundenlohn (€)</span>
|
||||
<input type="number" min="0" step="0.01" value={form.hourlyWage} onChange={updateField("hourlyWage")} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Zuschläge</span>
|
||||
<input value={form.allowancesDescription} onChange={updateField("allowancesDescription")} />
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Überstundenregelung</span>
|
||||
<input value={form.overtimeRules} onChange={updateField("overtimeRules")} />
|
||||
</label>
|
||||
|
||||
<div className="form-row">
|
||||
<label className="form-field">
|
||||
<span>Urlaubsanspruch (Tage/Jahr)</span>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={form.vacationDaysPerYear}
|
||||
onChange={updateField("vacationDaysPerYear")}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="form-field">
|
||||
<span>Probezeit (Monate)</span>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={form.probationPeriodMonths}
|
||||
onChange={updateField("probationPeriodMonths")}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FormActions({ onCancel, isSaving, submitLabel }) {
|
||||
return (
|
||||
<div className="form-actions">
|
||||
<OmsorgButton variant="secondary" type="button" onClick={onCancel} disabled={isSaving}>
|
||||
Abbrechen
|
||||
</OmsorgButton>
|
||||
<OmsorgButton type="submit" disabled={isSaving}>
|
||||
{isSaving ? "Speichert..." : submitLabel}
|
||||
</OmsorgButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user