Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
fdb5498
feat(xJustiz): list invalid xjustiz chars in the field error without
m0dh4x Aug 17, 2026
16e1f9f
feat(xJustiz): show the rejected characters in the field error in a list
m0dh4x Aug 17, 2026
023c227
Merge origin/main into
m0dh4x Aug 17, 2026
72b752d
Merge branch 'main' into APL-215-Implement-error-messages-for-xJustiz…
m0dh4x Aug 18, 2026
0028d9f
format(xjustixDatatype): use double quoutes instead of single quotes
m0dh4x Aug 18, 2026
2af0037
Merge branch 'APL-215-Implement-error-messages-for-xJustiz-data-valid…
m0dh4x Aug 18, 2026
8b86c92
format(xjustizDatatype): hmm dont know why the last change was'nt
m0dh4x Aug 18, 2026
4c7ada6
Merge branch 'main' into APL-215-Implement-error-messages-for-xJustiz…
m0dh4x Aug 18, 2026
cac7a07
chore(deps): bump a2j-xjustiz-converter to 0.4.1 and add standard-schema
m0dh4x Aug 19, 2026
bee44f5
refactor(xJustiz): integrate the datatypes as Zod schemas based on
m0dh4x Aug 19, 2026
96da1d7
test(xJustiz): construct sachverhaltBegruendung fixtures through the
m0dh4x Aug 19, 2026
49b368d
Merge branch 'APL-215-Implement-error-messages-for-xJustiz-data-valid…
m0dh4x Aug 19, 2026
00c4472
Merge origin/main into
m0dh4x Aug 20, 2026
395d620
fix(xJustiz): restore the fixture value in getItemValueBox test
m0dh4x Aug 20, 2026
3388f15
format(xJustiz): fix format errors textarea and xjustizDatatype
m0dh4x Aug 20, 2026
e75d8e0
Merge origin/main into
m0dh4x Aug 21, 2026
e2bd18f
chore(deps): rename a2j-xjustiz-converter to a2j-xjustiz-bridge
m0dh4x Aug 21, 2026
fb63848
Merge branch 'main' into APL-215-Implement-error-messages-for-xJustiz…
m0dh4x Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import { describe, expect, test } from "vitest";
import { type UserData } from "~/domains/userData";
import { type Translations } from "~/services/translations/getTranslationByKey";
Expand Down Expand Up @@ -137,7 +138,7 @@ describe("getItemValueBox", () => {
describe("extractFieldItemsFromInlineItems", () => {
it("extracts fieldName and fieldValue pairs for simple and nested fields", () => {
const userData: UserData = {
sachverhaltBegruendung: "Free text",
sachverhaltBegruendung: datatypeC("Free text").value,
weiterePersonen: { buchungsnummer: "ABCDEF10" },
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import { type TestCases } from "~/domains/__test__/TestCases";
import { type GeldEinklagenFormularUserData } from "../../userData";

Expand Down Expand Up @@ -26,7 +27,7 @@ const baseContext: GeldEinklagenFormularUserData = {
klagendePersonPlz: ZIP_CODE_PILOT_COURT,
klagendePersonOrt: "klagendePersonOrt",
forderungGesamtbetrag: "100.00",
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
pageData: {
subflowDoneStates: {
"/klage-erstellen/klagende-person": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import type { ExpectedStep, FlowTestCases } from "~/domains/__test__/TestCases";
import { type GeldEinklagenFormularUserData } from "../../userData";

Expand All @@ -14,7 +15,7 @@ const baseContext: GeldEinklagenFormularUserData = {
mietePachtRaum: "yes",
postleitzahlSecondary: ZIP_CODE_PILOT_COURT,
forderungGesamtbetrag: "100.00",
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
pageData: {
subflowDoneStates: {
"/gericht-pruefen/sachgebiet": true,
Expand Down Expand Up @@ -91,7 +92,7 @@ export const testCasesWithUserInputKlagenErstellen: FlowTestCases<GeldEinklagenF
{
stepId: "/klage-erstellen/sachverhalt/begruendung",
userInput: {
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
},
},
{
Expand Down Expand Up @@ -145,7 +146,7 @@ export const testCasesWithUserInputKlagenErstellen: FlowTestCases<GeldEinklagenF
{
stepId: "/klage-erstellen/sachverhalt/begruendung",
userInput: {
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
},
},
{
Expand Down Expand Up @@ -194,7 +195,7 @@ export const testCasesWithUserInputKlagenErstellen: FlowTestCases<GeldEinklagenF
{
stepId: "/klage-erstellen/sachverhalt/begruendung",
userInput: {
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
},
},
{
Expand Down Expand Up @@ -242,7 +243,7 @@ export const testCasesWithUserInputKlagenErstellen: FlowTestCases<GeldEinklagenF
{
stepId: "/klage-erstellen/sachverhalt/begruendung",
userInput: {
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
},
},
{
Expand Down Expand Up @@ -311,7 +312,7 @@ export const testCasesWithUserInputKlagenErstellen: FlowTestCases<GeldEinklagenF
{
stepId: "/klage-erstellen/sachverhalt/begruendung",
userInput: {
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
},
},
{
Expand Down
3 changes: 2 additions & 1 deletion app/domains/geldEinklagen/formular/klage-erstellen/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
stringRequiredMaxSchema,
} from "~/services/validation/stringRequired";
import { YesNoAnswer } from "~/services/validation/YesNoAnswer";
import { datatypeC } from "~/services/validation/xjustiz/xjustizDatatype";

const TEXTAREA_MAX_LENGTH = 60000;

Expand Down Expand Up @@ -138,7 +139,7 @@ export const geldEinklagenKlageErstellenPages = {
pageSchema: {
sachverhaltBegruendung: stringRequiredMaxSchema({
max: TEXTAREA_MAX_LENGTH,
}),
}).pipe(datatypeC),
},
},
beweiseAngebot: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import type { ExpectedStep, FlowTestCases } from "~/domains/__test__/TestCases";
import { type GeldEinklagenFormularUserData } from "../../../userData";

Expand Down Expand Up @@ -29,7 +30,7 @@ const baseContext: GeldEinklagenFormularUserData = {
beklagteTitle: "none",
beklagteVorname: "beklagteVorname",
beklagteNachname: "beklagteNachname",
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
beweiseAngebot: "no",
forderungGesamtbetrag: "1000",
pageData: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import type { FlowTestCases } from "~/domains/__test__/TestCases";
import { type GeldEinklagenFormularUserData } from "../../../userData";

Expand Down Expand Up @@ -29,7 +30,7 @@ const baseContext: GeldEinklagenFormularUserData = {
beklagteTitle: "none",
beklagteVorname: "beklagteVorname",
beklagteNachname: "beklagteNachname",
sachverhaltBegruendung: "some reason",
sachverhaltBegruendung: datatypeC("some reason").value,
beweiseAngebot: "no",
forderungGesamtbetrag: "1000",
anwaltskosten: "10",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { datatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import {
mockPdfKitDocument,
mockPdfKitDocumentStructure,
Expand Down Expand Up @@ -35,7 +36,9 @@ describe("createReasonPage", () => {
it("should call the addFactsOfCases for the legal assessment section", () => {
const mockStruct = mockPdfKitDocumentStructure();
const mockDoc = mockPdfKitDocument(mockStruct, { start: 2, count: 2 });
const userData = { sachverhaltBegruendung: "Mein Sachverhalt" };
const userData = {
sachverhaltBegruendung: datatypeC("Mein Sachverhalt").value,
};

createReasonPage(mockDoc, mockStruct, userData);

Expand Down
5 changes: 5 additions & 0 deletions app/services/translations/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ export const translations = {
de: "Geben Sie Ihre Straße ein und wählen Sie diese anschließend aus der Trefferliste aus",
},
},
xjustiz: {
invalidCharacters: {
de: "Die folgenden Sonderzeichen sind für dieses Feld nicht erlaubt und müssen gelöscht oder ersetzt werden:",
},
},
arraySummary: {
arrayEditButtonLabel: {
de: "Bearbeiten",
Expand Down
37 changes: 37 additions & 0 deletions app/services/validation/xjustiz/xjustizDatatype.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { datatypeC as originalDatatypeC } from "@digitalservicebund/a2j-xjustiz-bridge/nachricht/zahlungsklage";
import type { StandardSchemaV1 } from "@standard-schema/spec";
import { z } from "zod";
import { translations } from "~/services/translations/translations";

const invalidCharacters = (characters: Readonly<Set<string>>) =>
`${translations.xjustiz.invalidCharacters.de} ${[...characters].join(", ")}`;

/**
* While Zod supports Standard Schemas natively, it doesn't allow them to be used
* with operators like `and` or `pipe`. For example,
* `someZodSchema.pipe(someStandardSchema)` is not allowed. This function takes
* a Standard Schema and constructs a fully integrated Zod schema from it.
* Doing so, it takes into account possible input to output transformations by
* the validation function of the Standard Schema.
*/
function convertStandardSchemaToZod<Input, Output>(
schema: StandardSchemaV1<Input, Output>,
): z.ZodType<Output, Input> {
return z.any().transform((input, context) => {
const result = schema["~standard"].validate(input);

if (result instanceof Promise)
throw new Error("Asynchronous schemas are not supported");

if (result.issues) {
result.issues?.forEach((issue) => context.addIssue(issue.message));
return z.NEVER;
} else {
return result.value;
}
});
}

export const datatypeC = convertStandardSchemaToZod(
originalDatatypeC.customize({ invalidCharacters }),
);
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.1112.0",
"@digitalservicebund/a2j-xjustiz-bridge": "^0.6.0",
"@digitalservicebund/kern-ux-tailwind-theme": "^2.0.0",
"@kern-ux/native": "^2.5.0",
"@node-saml/node-saml": "github:digitalservicebund/node-saml#850e8e8d5e7f8c037f20e2d808bde05949b21916",
Expand Down Expand Up @@ -78,9 +79,9 @@
"pdf-lib": "^1.17.1",
"pdfkit": "^0.19.1",
"pino-http": "^11.0.0",
"prom-client": "^15.1.3",
"posthog-js": "1.417.4",
"posthog-node": "5.49.1",
"prom-client": "^15.1.3",
"rate-limit-redis": "^6.0.1",
"react": "^19.2.8",
"react-collapsed": "^4.2.0",
Expand All @@ -104,6 +105,7 @@
"@react-router/fs-routes": "^8.3.0",
"@rvf/react": "^8.1.3",
"@size-limit/file": "^13.0.3",
"@standard-schema/spec": "^1.1.0",
"@storybook/addon-a11y": "^10.5.8",
"@storybook/addon-docs": "^10.5.8",
"@storybook/react-vite": "^10.5.8",
Expand Down
29 changes: 29 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ trustPolicyExclude:
- chokidar@4.0.3 # solved by upgrading to 5.0.0, see https://github.com/paulmillr/chokidar/issues/1440
- semver@6.3.1 # solved by upgrading to 7.x
- hosted-git-info@6.1.3 # solved by upgrading to 6.1.4

minimumReleaseAgeExclude:
- "@digitalservicebund/a2j-xjustiz-bridge@0.6.0"