- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
'use client';
import { useMemo, useRef, useState } from 'react';
import { Button, Input } from 'react-aria-components';
import { Controller, useController, useForm, useFieldArray } from 'react-hook-form';
import classNames from 'classnames';
import { useTranslations } from 'next-intl';
import Card from '@/app/components/Card/Card';
import SingleSelect from '@/app/components/forms/SingleSelect/SingleSelect';
import InlineLoading from '@/app/components/loading/InlineLoading';
import { Toggle } from '@/app/components/Toggle/Toggle';
import { SettingsFormValues } from '@/types/forms';
import { filterOptionsBySearchTerm } from '@/utils/stringUtils';
import styles from './Settings.module.scss';
export default function SettingsPage() {
const [isFormLoading, setisFormLoading] = useState(false);
const [timezoneSearchTerm, setTimezoneSearchTerm] = useState<string | null>(
null,
);
const t = useTranslations('pages.OrganizationSettings.form');
const errorStrings = useTranslations(
'pages.OrganizationSettings.form-errors',
);
const timezoneOptions = useMemo(() => {
const timezones = Intl.supportedValuesOf('timeZone');
timezones.unshift('Etc/UTC');
return filterOptionsBySearchTerm(
timezones.map(tz => ({
id: tz,
name: tz === 'Etc/UTC' ? '(UTC+00:00) London' : tz.replace(/_/g, ' '),
})),
timezoneSearchTerm,
);
}, [timezoneSearchTerm]);
const formRef = useRef(null);
async function fetchData() {
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
delay(4000)
const requestValues: SettingsFormValues = {
timezone: 'Etc/UTC',
customUserFields: [{ name: 'field1', value: 'f1' }, { name: 'field2', value: 'f2' }, { name: 'field3', value: 'f3' }],
allowSkipPlacementTest: false,
proficientyTestFields: [{ days: 2 }, { days: 5 }, { days: 3 }, { days: 89 }],
};
return requestValues
}
const {
register,
control,
handleSubmit,
formState: { errors },
} = useForm({
defaultValues: async () => await fetchData()
});
//const { field } = useController({ name: 'test' });
const onSubmit = async (data: SettingsFormValues) => {
try {
setisFormLoading(true);
console.log(data);
setisFormLoading(false);
// TODO send to server
} catch (err: any) {
setisFormLoading(false);
console.log(err);
}
};
const { fields: customUserFields } = useFieldArray({ control, name: 'customUserFields' })
const { fields: proficientyTestFields } = useFieldArray({ control, name: 'proficientyTestFields' })
return (
<section className={styles.body}>
<form onSubmit={handleSubmit(onSubmit)}>
<Card>
<section className={styles['inner-card']}>
<div>
<p className={styles['card-title']}>{t('general-header')}</p>
</div>
<div className={styles['widget-text-bar']}></div>
<div className={styles.input}>
<label>{t('timezone-label')}</label>
<Controller
control={control}
disabled={false}
render={({ field }) => (
<SingleSelect
className={styles.dropdown}
disabled={false}
label={t('timezone-input-label')}
isLabelVisible={false}
options={timezoneOptions}
selectedOptionId={field.value}
setSelectedId={(selection: string[]) => {
field.onChange(selection[0] ?? 'UTC');
}}
dropdownArrowClassName={styles['caret']}
closeOnSelection={true}
searchable={true}
setSearchTerm={setTimezoneSearchTerm}
containerRef={formRef}
/>
)}
name="timezone"
/>
{errors.timezone && (
<p className={styles['input-error-msg']}>{errorStrings('invalid-timezone')}</p>
)}
</div>
</section>
{/************ Custom User Fields ***********/}
<section className={styles['inner-card']}>
<div>
<p className={styles['card-title']}>
{t('custom-user-fields-header')}
</p>
</div>
<div className={styles['widget-text-bar']}></div>
<p className={styles['card-subtitle']}>
{t('custom-user-fields-subheader')}
</p>
{
customUserFields.map((field: any, i: number) =>
<div className={styles.input} key={field.id}>
<label>{`${t('custom-user-field-label')} ${i + 1}`}</label>
<Input
aria-label={`${t('custom-user-field-label')} ${i}`}
type="text"
key={field.id}
{...register(`customUserFields.${i}.value`, { maxLength: 5 })}
className={styles['input-box']}
/>
{errors.customUserFields?.[i] && <p>This cant be more than 5 chars</p>}
</div>
)
}
</section>
{/************ Proficiency / Assessments Tests ***********/}
<section className={styles['inner-card']}>
<div>
<p className={styles['card-title']}>
{t('assessment-tests-header')}
</p>
</div>
<div className={styles['widget-text-bar']}></div>
<p className={styles['card-subtitle']}>
{t('assessment-tests-subheader')}
</p>
<div className={classNames(styles.input, styles.row)}>
<Controller
control={control}
render={({ field: { onChange, value } }) => (
<Toggle
disabled={false}
id="allow-skip-placement-test"
name="allowSkipPlacementTest"
title={t('allow-skip-placement-test-label')}
selected={Boolean(value)}
onChange={onChange}
className={styles['label-text']}
/>
)}
name="allowSkipPlacementTest"
/>
</div>
{
proficientyTestFields.map((field: any, i: number) =>
<div className={styles.input} key={field.id}>
<label>Proficiency test {i} interval</label>
<Input
aria-label={`Proficiency test ${i} interval`}
type="text"
key={field.id}
{...register(`proficientyTestFields.${i}.days`, { required: "yes!" })}
className={styles['input-box']}
/>
<span>{t('days')}</span>
{errors.proficientyTestFields?.[i] && <p className={styles['input-error-msg']}>
{errorStrings('numeric')}
</p>}
</div>
)
}
</section>
<div className={styles['form-footer']}>
<Button type="submit" className={styles['save-button']}>
{isFormLoading ? <InlineLoading /> : 'Save'}
</Button>
</div>
</Card>
</form>
</section>
);
}