.claude/skills/form-migration/SKILL.md
Admin-Formular auf Zod + React Hook Form migrieren
npx skillsauth add AImitSK/resa-wp form-migrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Migriert eine Admin-Komponente von useState-basierter Formularlogik auf Zod + React Hook Form.
Komponente analysieren:
docs/refactoring/form-validation-migration.md für StatusZod Schema erstellen:
src/admin/schemas/{name}.tsz.infer<>src/admin/schemas/index.tsKomponente migrieren:
Build prüfen:
npm run build ausführenCheckliste aktualisieren:
docs/refactoring/form-validation-migration.md aktualisierenSiehe src/admin/components/settings/GdprTab.tsx als vollständiges Beispiel.
// src/admin/schemas/{name}.ts
import { z } from 'zod';
import { __ } from '@wordpress/i18n';
export const {name}Schema = z.object({
// String-Feld (required)
fieldName: z
.string()
.min(1, __('Feldname ist erforderlich', 'resa')),
// String-Feld mit optionaler URL
url: z
.string()
.refine(
(val) => val === '' || /^https?:\/\/.+/.test(val),
__('Bitte eine gültige URL eingeben', 'resa'),
),
// Zahl-Feld (für Select mit parseInt)
numericField: z.number().int().min(0),
// Boolean (Switch/Checkbox)
booleanField: z.boolean(),
});
export type {Name}FormData = z.infer<typeof {name}Schema>;
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { {name}Schema, type {Name}FormData } from '../../schemas/{name}';
export function {Name}Tab() {
const { data: settings, isLoading } = use{Name}Settings();
const saveMutation = useSave{Name}Settings();
const defaults: {Name}FormData = {
// Default-Werte
};
const form = useForm<{Name}FormData>({
resolver: zodResolver({name}Schema),
defaultValues: defaults,
});
// Server-Daten synchronisieren
useEffect(() => {
if (settings) {
form.reset(settings);
}
}, [settings, form]);
const onSubmit = (data: {Name}FormData) => {
saveMutation.mutate(data, {
onSuccess: () => {
form.reset(data);
toast.success(__('Gespeichert.', 'resa'));
},
onError: () => {
toast.error(__('Fehler beim Speichern.', 'resa'));
},
});
};
if (isLoading) {
return <LoadingState message={__('Lade...', 'resa')} />;
}
const { formState: { isDirty, errors } } = form;
return (
// JSX mit form.register, Controller, errors
);
}
<Input
{...form.register('fieldName')}
style={{
...inputStyles,
borderColor: errors.fieldName ? '#ef4444' : undefined,
}}
/>;
{
errors.fieldName && (
<p style={{ fontSize: '13px', color: '#ef4444', margin: 0 }}>{errors.fieldName.message}</p>
);
}
<Controller
name="numericField"
control={form.control}
render={({ field }) => (
<select
value={field.value}
onChange={(e) => field.onChange(parseInt(e.target.value, 10))}
style={selectStyles}
>
{options.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))}
</select>
)}
/>
<Controller
name="booleanField"
control={form.control}
render={({ field }) => <Switch checked={field.value} onCheckedChange={field.onChange} />}
/>
<Button onClick={form.handleSubmit(onSubmit)} disabled={!isDirty || saveMutation.isPending}>
{saveMutation.isPending && <Spinner />}
{__('Speichern', 'resa')}
</Button>
Prüfe docs/refactoring/form-validation-migration.md für die vollständige Liste.
Verbleibend (Stand 2026-03-08):
TrackingTab.tsx — trackingSettingsSchemaWebhooksTab.tsx — webhookSchemaApiKeysTab.tsx — apiKeySchemaMessengerTab.tsx — messengerSchemaPropstackTab.tsx — propstackSettingsSchemaRecaptchaTab.tsx — recaptchaSettingsSchemaSetupTab.tsx — moduleSetupSchemaPdfTab.tsx — pdfSettingsSchemaLocationValuesTab.tsx — locationValuesSchemaTemplateEditor.tsx — emailTemplateSchemaLocationEditor.tsx — locationSchemaFactorEditor.tsx — factorSchemaSettings.tsx — generalSettingsSchemaPdfTemplates.tsx — pdfTemplateSchema__() wrappen#ef4444parseInt() für numerische Werteform.reset(data) nach erfolgreichem Save um isDirty zurückzusetzendevelopment
Use when building UIs leveraging the WordPress Design System (WPDS) and its components, tokens, patterns, etc.
tools
Use when working with WP-CLI (wp) for WordPress operations: safe search-replace, db export/import, plugin/theme/user/content management, cron, cache flushing, multisite, and scripting/automation with wp-cli.yml.
tools
WordPress Security Patterns für Plugin-Entwicklung. Automatisch anwenden: Sanitization, Escaping, Nonces, Capability Checks, $wpdb->prepare(), REST API Permission Callbacks.
development
Use when building, extending, or debugging WordPress REST API endpoints/routes: register_rest_route, WP_REST_Controller/controller classes, schema/argument validation, permission_callback/authentication, response shaping, register_rest_field/register_meta, or exposing CPTs/taxonomies via show_in_rest.