Skip to content
This repository has been archived by the owner on Feb 16, 2024. It is now read-only.

fix: initial contract form #41

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useTranslation } from 'react-i18next';
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from 'Components/ui/dropdown-menu';
import { useState } from 'react';
import DurationIndex from './duration/DurationIndex';

const DurationAndTimeout = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const DurationAndTimeout = () => {
const DurationTypeDropdown = () => {

const { t } = useTranslation();
const [isDurationOpen, setDurationOpen] = useState(false);
const [selectedDuration, setSelectedDuration] = useState(t('duration'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be using a key to keep track of the selection. It we use the translated value it won't work properly when we switch language.


const handleDurationToggle = () => setDurationOpen(prev => !prev);

const handleDurationSelect = (value: string) => setSelectedDuration(value);
const dropDownValues = [t('duration'), t('end time')];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const dropDownValues = [t('duration'), t('end time')];
const dropDownValues = [t('Duration'), t('End time')];


return (
<div className='flex items-center justify-start'>
<DropdownMenu onOpenChange={handleDurationToggle}>
<DropdownMenuTrigger className='drop-down-trigger w-40'>
<div className='flex items-center justify-around'>
<div>{selectedDuration}</div>

<img
src='/images/pages/header/ic-chevron-down.svg'
alt='arrow'
className={`ml-2 transition-transform ${isDurationOpen ? 'rotate-180' : ''}`}
/>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className='drop-down-content w-40'>
{dropDownValues.map(value => (
<DropdownMenuItem
key={value}
className={value === selectedDuration ? 'drowdown-item-selected' : 'drowdown-item'}
onClick={() => handleDurationSelect(value)}
>
<span>{value}</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{selectedDuration === 'duration' && <DurationIndex />}
</div>
);
};

export default DurationAndTimeout;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import TimeDropDown from './TimeDropDown';
import DurationInputField from './DurationInputField';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';

const DurationIndex = () => {
const { t } = useTranslation();

const [selectedTimeFrame, setSelectedTimeFrame] = useState(t('minutes'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Use keys to keep track of the selection.

return (
<>
<DurationInputField selectedTimeFrame={selectedTimeFrame} />
<TimeDropDown selectedTimeFrame={selectedTimeFrame} setSelectedTimeFrame={setSelectedTimeFrame} />
</>
);
};

export default DurationIndex;
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useTranslation } from 'react-i18next';
import { ChangeEvent, useEffect, useState } from 'react';
import Input from 'Components/ui/input';

type DurationInputFieldProps = {
selectedTimeFrame: string;
};

const DurationInputField = ({ selectedTimeFrame }: DurationInputFieldProps) => {
const { t } = useTranslation();

type TTimeFrameConfig = Record<string, number>;

type ThintValuesAndMessages = Record<string, TTimeFrameConfig>;

const hintValuesAndMessages: ThintValuesAndMessages = {
minutes: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be created dynamically based on contracts_for response.

min: 15,
max: 1440,
},
hours: {
min: 1,
max: 24,
},
days: {
min: 1,
max: 365,
},
};

const [inputValue, setInputValue] = useState({
value: '',
hasError: false,
hintMessage: t('Minimum 15'),
});

useEffect(() => {
const timeFrameConfig: TTimeFrameConfig = hintValuesAndMessages?.[selectedTimeFrame] || { min: 0, max: 0 };
setInputValue({ value: '', hasError: false, hintMessage: t(`Minimum ${timeFrameConfig.min}`) });
}, [selectedTimeFrame]);

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
const isValidInput = /^$|^[0-9]{1,4}$/.test(inputValue);

if (isValidInput) {
const timeFrameConfig: TTimeFrameConfig = hintValuesAndMessages?.[selectedTimeFrame] || { min: 0, max: 0 };
const value = parseInt(inputValue);
let hasError = false;
let hintMessage = t(`Minimum ${timeFrameConfig.min}`);

if (value < timeFrameConfig.min) {
hasError = true;
hintMessage = t(`Minimum ${timeFrameConfig.min}`);
} else if (value > timeFrameConfig.max) {
hasError = true;
hintMessage = t(`Maximum ${timeFrameConfig.max}`);
}

setInputValue({ value: inputValue, hasError, hintMessage });
}
};
return (
<div className='w-40'>
<Input
type='text'
id='exampleInput'
value={inputValue.value}
onChange={handleChange}
labelAlignment='left'
hint={inputValue.hintMessage}
error={inputValue.hasError}
/>
</div>
);
};

export default DurationInputField;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useTranslation } from 'react-i18next';
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from 'Components/ui/dropdown-menu';
import { useState } from 'react';

type TimeDropDownProps = {
selectedTimeFrame: string;
setSelectedTimeFrame: React.Dispatch<React.SetStateAction<string>>;
};

const TimeDropDown = ({ selectedTimeFrame, setSelectedTimeFrame }: TimeDropDownProps) => {
const { t } = useTranslation();
const [isDropDownOpen, setDropDownOpen] = useState(false);

const handleTimeToggle = () => setDropDownOpen(prev => !prev);

const handleDurationSelect = (value: string) => setSelectedTimeFrame(value);

const dropDownValues = [t('minutes'), t('hours'), t('days')];

return (
<DropdownMenu onOpenChange={handleTimeToggle}>
<DropdownMenuTrigger className='drop-down-trigger w-40'>
<div className='flex items-center justify-around'>
<div>{selectedTimeFrame}</div>
<img
src='/images/pages/header/ic-chevron-down.svg'
alt='arrow'
className={`ml-2 transition-transform ${isDropDownOpen ? 'rotate-180' : ''}`}
/>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className='drop-down-content w-40'>
{dropDownValues.map(value => (
<DropdownMenuItem
key={value}
className={value === selectedTimeFrame ? 'drowdown-item-selected' : 'drowdown-item'}
onClick={() => handleDurationSelect(value)}
>
<span>{value}</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
};

export default TimeDropDown;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const TimeOut = () => <div>Time out</div>;

export default TimeOut;
3 changes: 0 additions & 3 deletions src/components/trade-dashboard/duration/index.tsx

This file was deleted.

50 changes: 50 additions & 0 deletions src/components/trade-dashboard/start-time/StartTime.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useTranslation } from 'react-i18next';
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
} from 'Components/ui/dropdown-menu';
import { useState } from 'react';

const StartTime = () => {
const { t } = useTranslation();
const [isDropDownOpen, setDropdownOpen] = useState(false);

const handleDropdownToggle = () => {
setDropdownOpen(prev => !prev);
};

return (
<div className='flex items-center justify-start'>
<span className='text-m mr-3 font-light'> {t('Start time')}</span>
<DropdownMenu onOpenChange={handleDropdownToggle}>
<DropdownMenuTrigger className='drop-down-trigger w-40'>
<div className='flex items-center justify-around'>
<div>Now</div>
<img
src='/images/pages/header/ic-chevron-down.svg'
alt='arrow'
className={`ml-2 transition-transform ${isDropDownOpen ? 'rotate-180' : ''}`}
/>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className='drop-down-content w-40'>
<DropdownMenuItem className='drowdown-item-selected'>
<span>Now</span>
</DropdownMenuItem>
<DropdownMenuItem className='drowdown-item'>
<span>Item 2</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className='drowdown-item'>
<span>Item 3</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
};

export default StartTime;
3 changes: 0 additions & 3 deletions src/components/trade-dashboard/start-time/index.tsx

This file was deleted.

6 changes: 6 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import App from './App';
import APIProvider from 'Utils/websocket/APIProvider';
import 'Styles/main.css';
import 'Translations/i18n.ts';
import StartTime from 'Components/trade-dashboard/start-time/StartTime';
import DurationAndTimeout from 'Components/trade-dashboard/duration-and-time-out/DurationAndTimeOut';

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<APIProvider>
<App />
<div className='ml-10 w-4/12 rounded-md border border-slate-200 p-5 shadow'>
<StartTime />
<DurationAndTimeout />
</div>
</APIProvider>
</React.StrictMode>
);
12 changes: 12 additions & 0 deletions src/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,15 @@
@apply text-[1.375rem];
}
}
.drowdown-item {
@apply bg-white p-2 hover:bg-slate-50 focus-visible:outline-transparent;
}
.drowdown-item-selected {
@apply bg-slate-100 p-2 focus-visible:outline-transparent;
}
.drop-down-trigger {
@apply border border-gray-200 p-1 focus-visible:outline-gray-100;
}
.drop-down-content {
@apply rounded shadow-md;
}
Loading