Skip to content

Commit

Permalink
Update exit form inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
anurag-roy committed Mar 6, 2023
1 parent 4d7edf4 commit 1916c81
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 20 deletions.
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
"@headlessui/react": "^1.7.13",
"@heroicons/react": "^2.0.16",
"kiteconnect-ts": "^0.4.5",
"lodash.startcase": "^4.4.0",
"next": "13.2.1",
"next-themes": "^0.2.1",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.3",
"@types/lodash.startcase": "^4.4.7",
"@types/node": "^18.14.1",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
Expand Down
94 changes: 94 additions & 0 deletions src/components/ComboBoxInputs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { cx } from '@/utils/ui';
import { Combobox } from '@headlessui/react';
import { CheckIcon, ChevronDownIcon } from '@heroicons/react/24/solid';
import startCase from 'lodash.startcase';
import { Dispatch, SetStateAction, useState } from 'react';

type ComboBoxProps = {
name: string;
items: string[];
selectedItem?: string;
setSelectedItem?: Dispatch<SetStateAction<string>>;
};

export function ComboBoxInput({
name,
items,
selectedItem,
setSelectedItem,
}: ComboBoxProps) {
const [query, setQuery] = useState('');
const filteredItems =
query === ''
? items
: items.filter((i) => i.toLowerCase().includes(query.toLowerCase()));
return (
<Combobox
as="div"
defaultValue={items[0]}
value={selectedItem ? selectedItem : undefined}
onChange={setSelectedItem ? setSelectedItem : undefined}
className="max-w-sm"
>
<Combobox.Label className="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
{startCase(name)}
</Combobox.Label>
<div className="relative mt-1">
<Combobox.Input
name={name}
className="w-full rounded-md border border-zinc-300 bg-white dark:bg-zinc-900 dark:text-zinc-100 dark:border-zinc-700 py-2 pl-3 pr-10 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 sm:text-sm"
onChange={(event) => setQuery(event.target.value)}
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
<ChevronDownIcon
className="h-5 w-5 text-zinc-400"
aria-hidden="true"
/>
</Combobox.Button>

{filteredItems.length > 0 && (
<Combobox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-zinc-800 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 dark:ring-white/10 focus:outline-none sm:text-sm">
{filteredItems.map((s) => (
<Combobox.Option
key={s}
value={s}
className={({ active }) =>
cx(
'relative cursor-default select-none py-2 pl-3 pr-9',
active
? 'bg-blue-600 text-white'
: 'text-zinc-900 dark:text-zinc-100'
)
}
>
{({ active, selected }) => (
<>
<span
className={cx(
'block truncate',
selected && 'font-semibold'
)}
>
{s}
</span>

{selected && (
<span
className={cx(
'absolute inset-y-0 right-0 flex items-center pr-4',
active ? 'text-white' : 'text-blue-600'
)}
>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
)}
</>
)}
</Combobox.Option>
))}
</Combobox.Options>
)}
</div>
</Combobox>
);
}
65 changes: 47 additions & 18 deletions src/components/exit/ExitForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Instrument } from '@/types';
import { getExpiryOptions } from '@/utils/ui';
import { FormEvent, useState } from 'react';
import { FormEvent, useEffect, useState } from 'react';
import { ComboBoxInput } from '../ComboBoxInputs';
import { ExitTable } from './ExitTable';

const expiryOptions = getExpiryOptions();
Expand All @@ -10,6 +11,14 @@ export function ExitForm() {
const [instruments, setInstruments] = useState<Instrument[]>([]);
const [entryBasis, setEntryBasis] = useState(0);

const [stocks, setStocks] = useState([]);

useEffect(() => {
fetch('/api/getStocks')
.then((res) => res.json())
.then((response) => setStocks(response));
}, []);

const handleFormSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();

Expand Down Expand Up @@ -38,20 +47,38 @@ export function ExitForm() {
className="mb-12 rounded-lg rounded-t-none py-6 bg-zinc-50 dark:bg-zinc-800 dark:bg-white/5 border border-t-0 border-zinc-200 dark:border-white/10 flex justify-between items-end px-8"
onSubmit={handleFormSubmit}
>
<ComboBoxInput items={stocks} name="stock" />
<div>
<label
htmlFor="entryBasis"
htmlFor="expiry"
className="block text-sm font-medium text-zinc-800 dark:text-zinc-100"
>
Exit Diff %
Expiry
</label>
<select
id="expiry"
name="expiry"
className="mt-1 pl-3 pr-10 py-2 dark:bg-zinc-900 dark:text-white border-zinc-300 dark:border-zinc-700 focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-sm rounded-md"
>
{expiryOptions.map((o) => (
<option key={o} value={o}>
{o}
</option>
))}
</select>
</div>
<div>
<label
htmlFor="exitDiff"
className="block text-sm font-medium text-zinc-800 dark:text-zinc-100"
>
Exit Diff
</label>
<div className="mt-1">
<input
type="number"
defaultValue={0}
step={0.0001}
min={0}
max={100}
name="exitDiff"
id="exitDiff"
className="dark:bg-zinc-900 dark:text-white shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm border-zinc-300 dark:border-zinc-700 rounded-md "
Expand All @@ -60,23 +87,25 @@ export function ExitForm() {
</div>
<div>
<label
htmlFor="expiry"
htmlFor="entryBasis"
className="block text-sm font-medium text-zinc-800 dark:text-zinc-100"
>
Expiry
Exit Diff %
</label>
<select
id="expiry"
name="expiry"
className="mt-1 pl-3 pr-10 py-2 dark:bg-zinc-900 dark:text-white border-zinc-300 dark:border-zinc-700 focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-sm rounded-md"
>
{expiryOptions.map((o) => (
<option key={o} value={o}>
{o}
</option>
))}
</select>
<div className="mt-1">
<input
type="number"
defaultValue={0}
step={0.0001}
min={0}
max={100}
name="exitDiffPercent"
id="exitDiffPercent"
className="dark:bg-zinc-900 dark:text-white shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm border-zinc-300 dark:border-zinc-700 rounded-md "
/>
</div>
</div>

<button
type="submit"
className="px-8 py-2 text-base font-medium rounded-full bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
Expand Down
13 changes: 13 additions & 0 deletions src/pages/api/getStocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Instrument } from '@/types';
import { NextApiHandler } from 'next';
import { readFileSync } from 'node:fs';

const handler: NextApiHandler = async (req, res) => {
const nse = JSON.parse(
readFileSync('src/data/nse.json', 'utf-8')
) as Instrument[];

return res.json(nse.map((i) => i.tradingSymbol));
};

export default handler;
4 changes: 2 additions & 2 deletions src/pages/api/placeOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ const handler: NextApiHandler = async (req, res) => {
exchange: 'NSE',
order_type: 'LIMIT',
price: equityPrice,
product: 'CNC',
product: 'MIS',
quantity: quantity,
tradingsymbol: equityTradingSymbol,
transaction_type: type === 'ENRTY' ? 'BUY' : 'SELL',
transaction_type: type === 'ENTRY' ? 'BUY' : 'SELL',
};

const futureOrderBody: PlaceOrderParams = {
Expand Down

0 comments on commit 1916c81

Please sign in to comment.