add number input
This commit is contained in:
73
src/components/input/NumberInput.tsx
Normal file
73
src/components/input/NumberInput.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
|
||||
interface NumberInputProps {
|
||||
name?: string;
|
||||
error?: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
minValue?: number;
|
||||
maxValue?: number;
|
||||
onChange: (state: number) => void;
|
||||
defaultState?: number;
|
||||
}
|
||||
|
||||
export const NumberInput: React.FC<NumberInputProps> = ({
|
||||
error = '',
|
||||
// disabled = false,
|
||||
// required = false,
|
||||
label = '',
|
||||
placeholder = '',
|
||||
className = '',
|
||||
onChange,
|
||||
defaultState = 0,
|
||||
minValue = 0,
|
||||
maxValue = 365 * 24,
|
||||
name = '',
|
||||
}) => {
|
||||
const [value, setValue] = React.useState<number>(defaultState);
|
||||
|
||||
React.useEffect(() => onChange(value), [value]);
|
||||
React.useEffect(() => setValue(defaultState), [defaultState]);
|
||||
|
||||
return (
|
||||
<div className={cn('relative', className)}>
|
||||
<div
|
||||
className={cn(
|
||||
'text-[18px] text-liquid-white font-medium h-[23px] mb-[10px] transition-all',
|
||||
label == '' && 'h-0 mb-0',
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
<div className="relative pr-[5px]">
|
||||
<input
|
||||
className={cn(
|
||||
'bg-liquid-lighter w-full rounded-[10px] outline-none pl-[16px] pr-[8px] py-[8px] placeholder:text-liquid-light',
|
||||
)}
|
||||
value={value}
|
||||
name={name}
|
||||
type={'number'}
|
||||
min={minValue}
|
||||
max={maxValue}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) => {
|
||||
setValue(Number(e.target.value));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
'text-liquid-red text-[14px] h-auto text-right mt-[5px] whitespace-pre-line ',
|
||||
error == '' && 'h-0 mt-0',
|
||||
)}
|
||||
>
|
||||
{error}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
FilterDropDown,
|
||||
FilterItem,
|
||||
} from '../../../components/drop-down-list/Filter';
|
||||
import { SorterDropDown } from '../../../components/drop-down-list/Sorter';
|
||||
} from '../../../components/filters/Filter';
|
||||
import { SorterDropDown } from '../../../components/filters/Sorter';
|
||||
import { SearchInput } from '../../../components/input/SearchInput';
|
||||
|
||||
const Filters = () => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import Filters from './Filter';
|
||||
const Contests = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [modalActive, setModalActive] = useState<boolean>(false);
|
||||
const [modalActive, setModalActive] = useState<boolean>(true);
|
||||
|
||||
const { contests, status } = useAppSelector(
|
||||
(state) => state.contests.fetchContests,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
FilterDropDown,
|
||||
FilterItem,
|
||||
} from '../../../components/drop-down-list/Filter';
|
||||
import { SorterDropDown } from '../../../components/drop-down-list/Sorter';
|
||||
} from '../../../components/filters/Filter';
|
||||
import { SorterDropDown } from '../../../components/filters/Sorter';
|
||||
import { SearchInput } from '../../../components/input/SearchInput';
|
||||
|
||||
const Filters = () => {
|
||||
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
import { CreateContestBody } from '../../../redux/slices/contests';
|
||||
import DateRangeInput from '../../../components/input/DateRangeInput';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { NumberInput } from '../../../components/input/NumberInput';
|
||||
import { DropDownListItem } from '../../../components/filters/DropDownList';
|
||||
|
||||
function toUtc(localDateTime?: string): string {
|
||||
if (!localDateTime) return '';
|
||||
@@ -37,6 +39,12 @@ const ModalCreateContest: FC<ModalCreateContestProps> = ({
|
||||
(state) => state.contests.createContest.status,
|
||||
);
|
||||
|
||||
const scheduleTypeItems: DropDownListItem[] = [
|
||||
{value: "", text: ""},
|
||||
{value: "", text: ""},
|
||||
{value: "", text: ""},
|
||||
]
|
||||
|
||||
const [form, setForm] = useState<CreateContestBody>({
|
||||
name: '',
|
||||
description: '',
|
||||
@@ -110,8 +118,11 @@ const ModalCreateContest: FC<ModalCreateContestProps> = ({
|
||||
onChange={(v) => handleChange('description', v)}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-2 gap-[10px] mt-[10px]">
|
||||
<div>
|
||||
|
||||
<label className="block text-sm mb-1">
|
||||
Тип расписания
|
||||
</label>
|
||||
@@ -167,18 +178,16 @@ const ModalCreateContest: FC<ModalCreateContestProps> = ({
|
||||
|
||||
{/* Продолжительность и лимиты */}
|
||||
<div className="grid grid-cols-2 gap-[10px] mt-[10px]">
|
||||
<Input
|
||||
<NumberInput
|
||||
name="attemptDurationMinutes"
|
||||
type="number"
|
||||
label="Длительность попытки (мин)"
|
||||
placeholder="Например: 60"
|
||||
onChange={(v) =>
|
||||
handleChange('attemptDurationMinutes', Number(v))
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
<NumberInput
|
||||
name="maxAttempts"
|
||||
type="number"
|
||||
label="Макс. попыток"
|
||||
placeholder="Например: 3"
|
||||
onChange={(v) => handleChange('maxAttempts', Number(v))}
|
||||
@@ -186,7 +195,7 @@ const ModalCreateContest: FC<ModalCreateContestProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Разрешить раннее завершение */}
|
||||
<div className="flex items-center gap-[10px] mt-[15px]">
|
||||
{/* <div className="flex items-center gap-[10px] mt-[15px]">
|
||||
<input
|
||||
id="allowEarlyFinish"
|
||||
type="checkbox"
|
||||
@@ -198,7 +207,7 @@ const ModalCreateContest: FC<ModalCreateContestProps> = ({
|
||||
<label htmlFor="allowEarlyFinish">
|
||||
Разрешить раннее завершение
|
||||
</label>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* Кнопки */}
|
||||
<div className="flex flex-row w-full items-center justify-end mt-[20px] gap-[20px]">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
FilterDropDown,
|
||||
FilterItem,
|
||||
} from '../../../components/drop-down-list/Filter';
|
||||
import { SorterDropDown } from '../../../components/drop-down-list/Sorter';
|
||||
} from '../../../components/filters/Filter';
|
||||
import { SorterDropDown } from '../../../components/filters/Sorter';
|
||||
import { SearchInput } from '../../../components/input/SearchInput';
|
||||
|
||||
const Filters = () => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
setGroupsStatus,
|
||||
} from '../../../../redux/slices/groups';
|
||||
import ConfirmModal from '../../../../components/modal/ConfirmModal';
|
||||
import { DropDownList } from '../../../../components/drop-down-list/DropDownList';
|
||||
import { DropDownList } from '../../../../components/filters/DropDownList';
|
||||
import { ReverseButton } from '../../../../components/button/ReverseButton';
|
||||
|
||||
interface ModalUpdateProps {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import Editor from '@monaco-editor/react';
|
||||
import { upload } from '../../../assets/icons/input';
|
||||
import { cn } from '../../../lib/cn';
|
||||
import { DropDownList } from '../../../components/drop-down-list/DropDownList';
|
||||
import { DropDownList } from '../../../components/filters/DropDownList';
|
||||
|
||||
const languageMap: Record<string, string> = {
|
||||
c: 'cpp',
|
||||
|
||||
Reference in New Issue
Block a user