Skip to content

Commit

Permalink
Refactored Slippage and Est. gas forms to be editable.
Browse files Browse the repository at this point in the history
  • Loading branch information
dredshep committed Apr 3, 2024
1 parent 29753fc commit 96323d1
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 33 deletions.
76 changes: 76 additions & 0 deletions components/app/molecules/DynamicField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from "react";
import { FaPencilAlt, FaCheck } from "react-icons/fa"; // Importing check icon
import { StoreState, useStore } from "@/store/swapStore"; // Adjust the import path as necessary

interface DynamicFieldProps {
fieldIdentifier: keyof StoreState["sharedSettings"];
}

const DynamicField: React.FC<DynamicFieldProps> = ({ fieldIdentifier }) => {
const [isEditing, setIsEditing] = useState(false);
const [inputValue, setInputValue] = useState("");
const [isValid, setIsValid] = useState(true); // State to track validity
const fieldValue = useStore((state) => state.sharedSettings[fieldIdentifier]);
const setSharedSetting = useStore((state) => state.setSharedSetting);

const validateInput = (value: string): boolean => {
const parsedValue = parseFloat(value);
return !isNaN(parsedValue) && parsedValue >= 0; // Example validation: non-negative numbers
};

const handleEdit = () => {
setInputValue(fieldValue.toString());
setIsEditing(true);
setIsValid(true); // Reset validity when starting to edit
};

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
setIsValid(validateInput(e.target.value)); // Validate on every change
};

const handleSave = () => {
if (validateInput(inputValue)) {
setSharedSetting(fieldIdentifier, parseFloat(inputValue));
setIsEditing(false);
}
// No action on invalid input, maybe provide feedback
};

return (
<div className="flex items-center">
{isEditing ? (
<>
<input
type="text"
value={inputValue}
onChange={handleInputChange}
className={`rounded-l-xl h-6 text-sm font-bold py-2 px-4 box-border bg-adamant-app-input w-16 selection:bg-adamant-dark outline-transparent ${
!isValid ? "border-2 border-red-500 " : ""
}`}
autoFocus
/>
<button
onClick={handleSave}
className="bg-adamant-dark h-6 w-6 flex items-center justify-center rounded-r-xl text-white outline-none"
disabled={!isValid}
>
<FaCheck className="text-xs" />
</button>
</>
) : (
<>
<span className="text-sm selection:bg-white selection:text-blue-800">
{fieldValue}
</span>
<FaPencilAlt
onClick={handleEdit}
className="cursor-pointer text-xs ml-2"
/>
</>
)}
</div>
);
};

export default DynamicField;
2 changes: 1 addition & 1 deletion components/app/organisms/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const Navbar: React.FC = () => {
</div>
<UserWallet
isConnected={true}
userAddress="0x1234567890abcdef"
userAddress="secret1234567890abcdef"
balanceSCRT={0}
balanceADMT={0}
onConnect={() => console.log("connect")}
Expand Down
23 changes: 11 additions & 12 deletions components/app/organisms/SwapForm/SwapForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import InputLabel from "@/components/app/atoms/InputLabel";
import TokenInput from "@/components/app/molecules/TokenInput";
import SwapButton from "@/components/app/atoms/SwapButton";
import { useStore } from "@/store/swapStore"; // Ensure this path matches the location of your store
import DynamicField from "@/components/app/molecules/DynamicField";

const SwapFormWithState: React.FC = () => {
const SwapForm: React.FC = () => {
// You might want to fetch or calculate balances dynamically, as an example here
const balancePay = 100; // Example balance for pay
const balanceReceive = 100; // Example balance for receive
Expand Down Expand Up @@ -32,21 +33,19 @@ const SwapFormWithState: React.FC = () => {
</div>
{/* Implement inputs for slippage and estimated gas if they're managed by the store or elsewhere */}
<div className="flex justify-between normal-case">
<InputLabel label="Slippage" caseType="normal-case" />
<input
className="rounded-xl text-sm font-bold py-2 px-4 bg-adamant-app-input w-20"
placeholder="0.5%"
/>
<InputLabel label="Est. gas:" caseType="normal-case" />
<input
className="rounded-xl text-sm font-bold py-2 px-4 bg-adamant-app-input w-20"
placeholder="0.0"
/>
<div className="flex justify-between normal-case gap-2">
<InputLabel label="Slippage" caseType="normal-case" />
<DynamicField fieldIdentifier="slippage" />
</div>
<div className="flex justify-between normal-case gap-2">
<InputLabel label="Est. gas:" caseType="normal-case" />
<DynamicField fieldIdentifier="gas" />
</div>
</div>
</div>
<SwapButton disabled={false} onClick={handleSwapClick} />
</div>
);
};

export default SwapFormWithState;
export default SwapForm;
4 changes: 2 additions & 2 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import "@/styles/globals.css";
import "@radix-ui/themes/styles.css";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { Theme } from "@radix-ui/themes";

export default function App({ Component, pageProps }: AppProps) {
return (
<Theme>
<Theme color="black" grayColor="olive" accentColor="amber">
<Component {...pageProps} />
</Theme>
);
Expand Down
43 changes: 25 additions & 18 deletions store/swapStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,31 @@ interface TokenInputState {
amount: string;
}

// Extending TokenInputs to hold identifiers for gas and slippage
export interface TokenInputs {
"swap.pay": TokenInputState;
"swap.receive": TokenInputState;
}

interface StoreState {
tokenInputs: TokenInputs;
// New structure for shared settings like gas and slippage across forms
interface SharedSettings {
slippage: number;
gas: number;
}

export interface StoreState {
tokenInputs: TokenInputs;
sharedSettings: SharedSettings; // Shared settings for transactions
setTokenInputProperty: <T extends keyof TokenInputState>(
inputIdentifier: keyof TokenInputs,
property: T,
value: TokenInputState[T]
) => void;
setSlippage: (slippage: number) => void;
setGas: (gas: number) => void;
// Generalizing setters for shared settings
setSharedSetting: <T extends keyof SharedSettings>(
setting: T,
value: SharedSettings[T]
) => void;
}

export const useStore = create<StoreState>((set) => ({
Expand All @@ -35,8 +44,10 @@ export const useStore = create<StoreState>((set) => ({
amount: "",
},
},
slippage: 0.5,
gas: 0,
sharedSettings: {
slippage: 0.5,
gas: 0,
},
setTokenInputProperty: <T extends keyof TokenInputState>(
inputIdentifier: keyof TokenInputs,
property: T,
Expand All @@ -52,16 +63,12 @@ export const useStore = create<StoreState>((set) => ({
},
},
})),
setSlippage: (slippage: number) => set({ slippage }),
setGas: (gas: number) => set({ gas }),
setSharedSetting: <T extends keyof SharedSettings>(
setting: T,
value: SharedSettings[T]
) =>
set((state) => ({
...state,
sharedSettings: { ...state.sharedSettings, [setting]: value },
})),
}));

// const adjustTokenExample = (inputIdentifier: keyof TokenInputs, token: Token) => {
// const store = useStore();
// store.setTokenInputProperty(inputIdentifier, 'token', token);
// };

// const adjustAmountExample = (inputIdentifier: keyof TokenInputs, amount: string) => {
// const store = useStore();
// store.setTokenInputProperty(inputIdentifier, 'amount', amount);
// };

0 comments on commit 96323d1

Please sign in to comment.