Tue Aug 26 2025
Copied to clipboard! Copy reply
  • 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>
  );
}