mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 09:12:02 +10:00
feat: web i18n (#1286)
This commit is contained in:
@ -2,6 +2,8 @@
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { ChevronDown, ChevronUp, Trash } from 'lucide-react';
|
||||
|
||||
import { validateCheckboxField } from '@documenso/lib/advanced-fields-validation/validate-checkbox';
|
||||
@ -35,6 +37,8 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
handleFieldChange,
|
||||
handleErrors,
|
||||
}: CheckboxFieldAdvancedSettingsProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const [showValidation, setShowValidation] = useState(false);
|
||||
const [values, setValues] = useState(fieldState.values ?? [{ id: 1, checked: false, value: '' }]);
|
||||
const [readOnly, setReadOnly] = useState(fieldState.readOnly ?? false);
|
||||
@ -122,13 +126,15 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-row items-center gap-x-4">
|
||||
<div className="flex w-2/3 flex-col">
|
||||
<Label>Validation</Label>
|
||||
<Label>
|
||||
<Trans>Validation</Trans>
|
||||
</Label>
|
||||
<Select
|
||||
value={fieldState.validationRule}
|
||||
onValueChange={(val) => handleToggleChange('validationRule', val)}
|
||||
>
|
||||
<SelectTrigger className="text-muted-foreground bg-background mt-2 w-full">
|
||||
<SelectValue placeholder="Select at least" />
|
||||
<SelectValue placeholder={_(msg`Select at least`)} />
|
||||
</SelectTrigger>
|
||||
<SelectContent position="popper">
|
||||
{checkboxValidationRules.map((item, index) => (
|
||||
@ -145,7 +151,7 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
onValueChange={(val) => handleToggleChange('validationLength', val)}
|
||||
>
|
||||
<SelectTrigger className="text-muted-foreground bg-background mt-2 w-full">
|
||||
<SelectValue placeholder="Pick a number" />
|
||||
<SelectValue placeholder={_(msg`Pick a number`)} />
|
||||
</SelectTrigger>
|
||||
<SelectContent position="popper">
|
||||
{checkboxValidationLength.map((item, index) => (
|
||||
@ -164,7 +170,9 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
checked={fieldState.required}
|
||||
onCheckedChange={(checked) => handleToggleChange('required', checked)}
|
||||
/>
|
||||
<Label>Required field</Label>
|
||||
<Label>
|
||||
<Trans>Required field</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Switch
|
||||
@ -172,7 +180,9 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
checked={fieldState.readOnly}
|
||||
onCheckedChange={(checked) => handleToggleChange('readOnly', checked)}
|
||||
/>
|
||||
<Label>Read only</Label>
|
||||
<Label>
|
||||
<Trans>Read only</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@ -181,7 +191,9 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
onClick={() => setShowValidation((prev) => !prev)}
|
||||
>
|
||||
<span className="flex w-full flex-row justify-between">
|
||||
<span className="flex items-center">Checkbox values</span>
|
||||
<span className="flex items-center">
|
||||
<Trans>Checkbox values</Trans>
|
||||
</span>
|
||||
{showValidation ? <ChevronUp /> : <ChevronDown />}
|
||||
</span>
|
||||
</Button>
|
||||
@ -215,7 +227,7 @@ export const CheckboxFieldAdvancedSettings = ({
|
||||
variant="outline"
|
||||
onClick={addValue}
|
||||
>
|
||||
Add another value
|
||||
<Trans>Add another value</Trans>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { ChevronDown, ChevronUp, Trash } from 'lucide-react';
|
||||
|
||||
import { validateDropdownField } from '@documenso/lib/advanced-fields-validation/validate-dropdown';
|
||||
@ -32,6 +34,8 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
handleFieldChange,
|
||||
handleErrors,
|
||||
}: DropdownFieldAdvancedSettingsProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const [showValidation, setShowValidation] = useState(false);
|
||||
const [values, setValues] = useState(fieldState.values ?? [{ value: 'Option 1' }]);
|
||||
const [readOnly, setReadOnly] = useState(fieldState.readOnly ?? false);
|
||||
@ -87,7 +91,9 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
return (
|
||||
<div className="text-dark flex flex-col gap-4">
|
||||
<div>
|
||||
<Label>Select default option</Label>
|
||||
<Label>
|
||||
<Trans>Select default option</Trans>
|
||||
</Label>
|
||||
<Select
|
||||
defaultValue={defaultValue}
|
||||
onValueChange={(val) => {
|
||||
@ -96,7 +102,7 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="text-muted-foreground bg-background mt-2 w-full">
|
||||
<SelectValue defaultValue={defaultValue} placeholder="-- Select --" />
|
||||
<SelectValue defaultValue={defaultValue} placeholder={`-- ${_(msg`Select`)} --`} />
|
||||
</SelectTrigger>
|
||||
<SelectContent position="popper">
|
||||
{values.map((item, index) => (
|
||||
@ -117,7 +123,9 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
checked={fieldState.required}
|
||||
onCheckedChange={(checked) => handleToggleChange('required', checked)}
|
||||
/>
|
||||
<Label>Required field</Label>
|
||||
<Label>
|
||||
<Trans>Required field</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Switch
|
||||
@ -125,7 +133,9 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
checked={fieldState.readOnly}
|
||||
onCheckedChange={(checked) => handleToggleChange('readOnly', checked)}
|
||||
/>
|
||||
<Label>Read only</Label>
|
||||
<Label>
|
||||
<Trans>Read only</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@ -134,7 +144,9 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
onClick={() => setShowValidation((prev) => !prev)}
|
||||
>
|
||||
<span className="flex w-full flex-row justify-between">
|
||||
<span className="flex items-center">Dropdown options</span>
|
||||
<span className="flex items-center">
|
||||
<Trans>Dropdown options</Trans>
|
||||
</span>
|
||||
{showValidation ? <ChevronUp /> : <ChevronDown />}
|
||||
</span>
|
||||
</Button>
|
||||
@ -162,7 +174,7 @@ export const DropdownFieldAdvancedSettings = ({
|
||||
variant="outline"
|
||||
onClick={addValue}
|
||||
>
|
||||
Add another option
|
||||
<Trans>Add another option</Trans>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react';
|
||||
|
||||
import { validateNumberField } from '@documenso/lib/advanced-fields-validation/validate-number';
|
||||
@ -31,6 +33,8 @@ export const NumberFieldAdvancedSettings = ({
|
||||
handleFieldChange,
|
||||
handleErrors,
|
||||
}: NumberFieldAdvancedSettingsProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const [showValidation, setShowValidation] = useState(false);
|
||||
|
||||
const handleInput = (field: keyof NumberFieldMeta, value: string | boolean) => {
|
||||
@ -56,43 +60,51 @@ export const NumberFieldAdvancedSettings = ({
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<Label>Label</Label>
|
||||
<Label>
|
||||
<Trans>Label</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="label"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Label"
|
||||
placeholder={_(msg`Label`)}
|
||||
value={fieldState.label}
|
||||
onChange={(e) => handleFieldChange('label', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="mt-4">Placeholder</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Placeholder</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="placeholder"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Placeholder"
|
||||
placeholder={_(msg`Placeholder`)}
|
||||
value={fieldState.placeholder}
|
||||
onChange={(e) => handleFieldChange('placeholder', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="mt-4">Value</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Value</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="value"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Value"
|
||||
placeholder={_(msg`Value`)}
|
||||
value={fieldState.value}
|
||||
onChange={(e) => handleInput('value', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Number format</Label>
|
||||
<Label>
|
||||
<Trans>Number format</Trans>
|
||||
</Label>
|
||||
<Select
|
||||
value={fieldState.numberFormat}
|
||||
onValueChange={(val) => handleInput('numberFormat', val)}
|
||||
>
|
||||
<SelectTrigger className="text-muted-foreground bg-background mt-2 w-full">
|
||||
<SelectValue placeholder="Field format" />
|
||||
<SelectValue placeholder={_(msg`Field format`)} />
|
||||
</SelectTrigger>
|
||||
<SelectContent position="popper">
|
||||
{numberFormatValues.map((item, index) => (
|
||||
@ -110,7 +122,9 @@ export const NumberFieldAdvancedSettings = ({
|
||||
checked={fieldState.required}
|
||||
onCheckedChange={(checked) => handleInput('required', checked)}
|
||||
/>
|
||||
<Label>Required field</Label>
|
||||
<Label>
|
||||
<Trans>Required field</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Switch
|
||||
@ -118,7 +132,9 @@ export const NumberFieldAdvancedSettings = ({
|
||||
checked={fieldState.readOnly}
|
||||
onCheckedChange={(checked) => handleInput('readOnly', checked)}
|
||||
/>
|
||||
<Label>Read only</Label>
|
||||
<Label>
|
||||
<Trans>Read only</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@ -127,14 +143,18 @@ export const NumberFieldAdvancedSettings = ({
|
||||
onClick={() => setShowValidation((prev) => !prev)}
|
||||
>
|
||||
<span className="flex w-full flex-row justify-between">
|
||||
<span className="flex items-center">Validation</span>
|
||||
<span className="flex items-center">
|
||||
<Trans>Validation</Trans>
|
||||
</span>
|
||||
{showValidation ? <ChevronUp /> : <ChevronDown />}
|
||||
</span>
|
||||
</Button>
|
||||
{showValidation && (
|
||||
<div className="mb-4 flex flex-row gap-x-4">
|
||||
<div className="flex flex-col">
|
||||
<Label className="mt-4">Min</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Min</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="minValue"
|
||||
className="bg-background mt-2"
|
||||
@ -144,7 +164,9 @@ export const NumberFieldAdvancedSettings = ({
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<Label className="mt-4">Max</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Max</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="maxValue"
|
||||
className="bg-background mt-2"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { ChevronDown, ChevronUp, Trash } from 'lucide-react';
|
||||
|
||||
import { validateRadioField } from '@documenso/lib/advanced-fields-validation/validate-radio';
|
||||
@ -107,7 +108,9 @@ export const RadioFieldAdvancedSettings = ({
|
||||
checked={fieldState.required}
|
||||
onCheckedChange={(checked) => handleToggleChange('required', checked)}
|
||||
/>
|
||||
<Label>Required field</Label>
|
||||
<Label>
|
||||
<Trans>Required field</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Switch
|
||||
@ -115,7 +118,9 @@ export const RadioFieldAdvancedSettings = ({
|
||||
checked={fieldState.readOnly}
|
||||
onCheckedChange={(checked) => handleToggleChange('readOnly', checked)}
|
||||
/>
|
||||
<Label>Read only</Label>
|
||||
<Label>
|
||||
<Trans>Read only</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@ -124,7 +129,9 @@ export const RadioFieldAdvancedSettings = ({
|
||||
onClick={() => setShowValidation((prev) => !prev)}
|
||||
>
|
||||
<span className="flex w-full flex-row justify-between">
|
||||
<span className="flex items-center">Radio values</span>
|
||||
<span className="flex items-center">
|
||||
<Trans>Radio values</Trans>
|
||||
</span>
|
||||
{showValidation ? <ChevronUp /> : <ChevronDown />}
|
||||
</span>
|
||||
</Button>
|
||||
@ -157,7 +164,7 @@ export const RadioFieldAdvancedSettings = ({
|
||||
variant="outline"
|
||||
onClick={addValue}
|
||||
>
|
||||
Add another value
|
||||
<Trans>Add another value</Trans>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
|
||||
import { validateTextField } from '@documenso/lib/advanced-fields-validation/validate-text';
|
||||
import { type TTextFieldMeta as TextFieldMeta } from '@documenso/lib/types/field-meta';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
@ -16,6 +19,8 @@ export const TextFieldAdvancedSettings = ({
|
||||
handleFieldChange,
|
||||
handleErrors,
|
||||
}: TextFieldAdvancedSettingsProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
const handleInput = (field: keyof TextFieldMeta, value: string | boolean) => {
|
||||
const text = field === 'text' ? String(value) : fieldState.text || '';
|
||||
const limit =
|
||||
@ -36,45 +41,53 @@ export const TextFieldAdvancedSettings = ({
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<Label>Label</Label>
|
||||
<Label>
|
||||
<Trans>Label</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="label"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Field label"
|
||||
placeholder={_(msg`Field label`)}
|
||||
value={fieldState.label}
|
||||
onChange={(e) => handleFieldChange('label', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="mt-4">Placeholder</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Placeholder</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="placeholder"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Field placeholder"
|
||||
placeholder={_(msg`Field placeholder`)}
|
||||
value={fieldState.placeholder}
|
||||
onChange={(e) => handleFieldChange('placeholder', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label className="mt-4">Add text</Label>
|
||||
<Label className="mt-4">
|
||||
<Trans>Add text</Trans>
|
||||
</Label>
|
||||
<Textarea
|
||||
id="text"
|
||||
className="bg-background mt-2"
|
||||
placeholder="Add text to the field"
|
||||
placeholder={_(msg`Add text to the field`)}
|
||||
value={fieldState.text}
|
||||
onChange={(e) => handleInput('text', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Character Limit</Label>
|
||||
<Label>
|
||||
<Trans>Character Limit</Trans>
|
||||
</Label>
|
||||
<Input
|
||||
id="characterLimit"
|
||||
type="number"
|
||||
min={0}
|
||||
className="bg-background mt-2"
|
||||
placeholder="Field character limit"
|
||||
placeholder={_(msg`Field character limit`)}
|
||||
value={fieldState.characterLimit}
|
||||
onChange={(e) => handleInput('characterLimit', e.target.value)}
|
||||
/>
|
||||
@ -87,7 +100,9 @@ export const TextFieldAdvancedSettings = ({
|
||||
checked={fieldState.required}
|
||||
onCheckedChange={(checked) => handleInput('required', checked)}
|
||||
/>
|
||||
<Label>Required field</Label>
|
||||
<Label>
|
||||
<Trans>Required field</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Switch
|
||||
@ -95,7 +110,9 @@ export const TextFieldAdvancedSettings = ({
|
||||
checked={fieldState.readOnly}
|
||||
onCheckedChange={(checked) => handleInput('readOnly', checked)}
|
||||
/>
|
||||
<Label>Read only</Label>
|
||||
<Label>
|
||||
<Trans>Read only</Trans>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user