Skip to content

Commit

Permalink
create new basket
Browse files Browse the repository at this point in the history
  • Loading branch information
hckrg committed Jul 17, 2023
1 parent 5fa1333 commit 513e65f
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 13 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@onflow/fcl": "^1.4.1",
"@vitejs/plugin-react": "^4.0.3",
"Buffer": "^0.0.0",
"axios": "^1.4.0",
"classnames": "^2.3.2",
"elliptic": "^6.5.4",
"react": "^18.2.0",
Expand All @@ -25,6 +26,7 @@
"recoil": "^0.7.7"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@types/elliptic": "^6.4.14",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
Expand Down
17 changes: 14 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import { RecoilRoot } from 'recoil'
import { atom, useRecoilState } from 'recoil'
import AppRoutes from './Routes'
import { useEffect } from 'react'
import * as fcl from '@onflow/fcl'

export const userAtom = atom<{loggedIn: boolean} | null>({
key: 'userAtom',
default: null
})

function App() {
// for any wrappers required on the entire app
const setUser = useRecoilState(userAtom)[1]

useEffect(() => {
fcl.currentUser.subscribe(setUser)
}, [])

return (
<RecoilRoot>
<AppRoutes />
</RecoilRoot>
)
}

Expand Down
21 changes: 15 additions & 6 deletions src/components/Dashboard_Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { useEffect, useState, useRef } from 'react';
import avatar from '../images/avatar.png';
import logo from '../images/logo.png';

import { useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { userAtom } from '../App';
import * as fcl from '@onflow/fcl'

const Dashboard_Navbar = ({ navbarShadow }: { navbarShadow: boolean }) => {
const [showLogout, setShowLogout] = useState(false);

const logoutRef = useRef<HTMLDivElement>(null);
const navigate = useNavigate()
const user = useRecoilValue(userAtom)

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
Expand Down Expand Up @@ -38,11 +44,11 @@ const Dashboard_Navbar = ({ navbarShadow }: { navbarShadow: boolean }) => {
<img src={logo} alt="logo" className="w-7 h-7" />
<div>Basket Protocol</div>
</div>
<button onClick={() => { }} className="bg-custom-500 text-white-100 font-bold py-2 px-6 rounded-lg cursor-pointer min-w-[140px]">Create Basket</button>
<button onClick={() => navigate('/create')} className="bg-custom-500 text-white-100 font-bold py-2 px-6 rounded-lg cursor-pointer min-w-[140px]">Create Basket</button>
</div>
<div className="right-1 top-9 fixed flex justify-center items-center space-x-2 hover:opacity-80 cursor-pointer transition duration-200" onClick={handleImageClick}>
<div>
<img src={avatar} alt="profile" className="w-11 h-11" />
{user?.loggedIn && <img src={avatar} alt="profile" className="w-11 h-11" />}
{showLogout && (
<div className="absolute right-6 sm:right-56 rounded-lg shadow-lg my-1 border" ref={logoutRef}>
<div className="flex space-x-2 px-2 sm:px-5 py-2 rounded-lg bg-white hover:bg-red-200 justify-center items-center">
Expand All @@ -51,9 +57,12 @@ const Dashboard_Navbar = ({ navbarShadow }: { navbarShadow: boolean }) => {
</div>
)}
</div>
<div className="text-gray-500 text-sm opacity-0 left-0 top-0 sm:pr-8 absolute sm:opacity-100 sm:static">
Anurag
</div>
{
user?.loggedIn ? <div className="text-gray-500 text-sm opacity-0 left-0 top-0 sm:pr-8 absolute sm:opacity-100 sm:static">
Anurag
</div> : <button onClick={async() => await fcl.authenticate()} className="bg-custom-500 text-white-100 font-bold py-2 px-6 rounded-lg cursor-pointer min-w-[140px]">Connect Wallet</button>

}
</div>
</>
);
Expand Down
34 changes: 34 additions & 0 deletions src/components/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export type ToggleSwitchProps = {
checked: boolean,
onChange: () => void,
label?: string | null,
id: string
}

function ToggleSwitch({ id, checked, onChange, label }: ToggleSwitchProps) {

return (
<div className="flex items-center justify-center">
<label htmlFor={id} className="flex items-center cursor-pointer">
{label &&
<div className="mx-3 text-gray-400 text-sm font-light">
{label}
</div>
}
<div className="relative">
<input
type="checkbox"
checked={checked}
onChange={onChange}
id={id}
className="sr-only"
/>
<div className="block toggle bg-gray-400 w-10 h-6 rounded-full"></div>
<div className="dot absolute left-1 top-1 bg-white-100 w-4 h-4 rounded-full transition"></div>
</div>
</label>
</div>
);
}

export default ToggleSwitch;
5 changes: 4 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { RecoilRoot } from 'recoil'

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>,
)
100 changes: 100 additions & 0 deletions src/pages/CreateBasket.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useState } from 'react'
import Dashboard_Navbar from '../components/Dashboard_Navbar'
import { allTokens, getTokenBySymbol } from '../utils/getTokenDetails'
import { TokenIcon } from './ExploreBasket'
import ToggleSwitch from '../components/ToggleSwitch'

export type tokenDetails = {
tokenName?: string,
tokenSymbol?: string,
tokenContractName?: string,
tokenIcon?: string
}

function CreateBasket() {
const [selectedTokens, setSelectedTokens] = useState<string[]>([])
const [tokenDetails, setTokenDetails] = useState<tokenDetails>()

const [selectedTokenValues, setSelectedTokenValues] = useState<Record<string, string>>({})
const data = allTokens[0]

const handleTokenDetailsChange = (key: keyof tokenDetails, value: string) => {
setTokenDetails((prev) => {
if (prev) return {...prev, [key]: value};
else return {[key]: value}
})
}

console.log(selectedTokens, selectedTokenValues)

return (
<div className="flex flex-col min-h-screen items-center bg-custom-400">
<Dashboard_Navbar navbarShadow />
<div className='flex flex-col items-center pb-10 md:w-2/3 w-5/6 bg-white-100 rounded-xl my-48 font-mono'>
<div className='flex w-full justify-between items-center p-10'>
<div className='text-custom-600 text-2xl font-medium'>Create Basket</div>
<button onClick={() => { }} className="bg-custom-500 text-white-100 font-bold py-2 px-6 rounded-lg cursor-pointer min-w-[140px]">Publish</button>
</div>
<hr className='bg-custom-400 w-5/6' />
<div className='flex flex-col w-full gap-4 items-center'>
<div className='font-mono my-4 text-gray-600'>Add Details about the Index Token</div>
<div className='flex items-center justify-center w-5/6 gap-4'>
<div className='w-full'>Display Name: </div>
<input
placeholder="Token Name"
value={tokenDetails?.tokenName ?? ""}
onChange={(e) => handleTokenDetailsChange("tokenName", e.target.value)}
className="rounded-md w-full text-base px-6 py-4 focus:outline-none border-b-[1px] border-gray-200"
/>
</div>
<div className='flex items-center w-5/6 gap-4'>
<div className='w-full'>Token Symbol (Preferably 3 letters): </div>
<input
placeholder="Token Symbol"
value={tokenDetails?.tokenSymbol ?? ""}
onChange={(e) => handleTokenDetailsChange("tokenSymbol", e.target.value)}
className="rounded-md w-full text-base px-6 py-4 focus:outline-none border-b-[1px] border-gray-200"
/>
</div>
<div className='flex items-center justify-center w-5/6 gap-4'>
<div className='w-full'>Token Contract Name : </div>
<input
placeholder="Token Contract Name"
value={tokenDetails?.tokenContractName ?? ""}
onChange={(e) => handleTokenDetailsChange("tokenContractName", e.target.value)}
className="rounded-md w-full text-base px-6 py-4 focus:outline-none border-b-[1px] border-gray-200"
/>
</div>
<hr className='bg-custom-600 my-8 w-5/6' />
<div className='text-custom-600 font-medium text-lg'>Choose Underlying Tokens</div>
<div className='text-gray-600 text-sm'>We source tokens from increment.fi </div>
<div className='flex flex-col items-center w-5/6'>
{
data.underlyingTokens.map(s => getTokenBySymbol(s)).map((token) => (
<div className="flex justify-between w-full py-6 px-10 ">
<TokenIcon logo={token?.logo} symbol={token?.name} />
<ToggleSwitch
id={token?.symbol!}
checked={selectedTokens.includes(token?.symbol!)}
onChange={() => selectedTokens.includes(token?.symbol!) ? setSelectedTokens((prev) => prev.filter(t => t!=token?.symbol)) : setSelectedTokens((prev) => [...prev, token?.symbol!])}
/>
{
selectedTokens.includes(token?.symbol!) &&
<input
placeholder={`${token?.symbol} value`}
value={selectedTokenValues[token?.symbol!] ?? ""}
onChange={(e) => setSelectedTokenValues((prev) => ({...prev, [token?.symbol!]: e.target.value}))}
className="rounded-md text-base px-2 focus:outline-none border-b-[1px] border-gray-200"
/>
}
</div>
))
}
</div>
</div>
</div>
</div>
)
}

export default CreateBasket
2 changes: 1 addition & 1 deletion src/pages/ExploreBasket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ type TokenIconProps = {
logo?: string
}

const TokenIcon = ({ logo, symbol }: TokenIconProps) => {
export const TokenIcon = ({ logo, symbol }: TokenIconProps) => {
return <div className="flex items-center gap-4 font-medium">
{logo && <img src={logo} className="h-7 w-7 rounded-full" />}
{symbol && <p>{symbol}</p>}
Expand Down
6 changes: 5 additions & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ export const tempTokens: baseToken[] = [
logo: "https://cdn.jsdelivr.net/gh/FlowFans/flow-token-list@main/token-registry/A.b19436aae4d94622.FiatToken/logo.svg",
decimals: 8,
},
];
];

export const pinataTokenJWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mb3JtYXRpb24iOnsiaWQiOiI2NTBhNDU2NS02ZjM0LTQ1YTYtYmVmOS04ZmIxMGE0NmVlN2EiLCJlbWFpbCI6ImdhdXJhdmRoYWxsYTE0OTNAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInBpbl9wb2xpY3kiOnsicmVnaW9ucyI6W3siaWQiOiJGUkExIiwiZGVzaXJlZFJlcGxpY2F0aW9uQ291bnQiOjF9LHsiaWQiOiJOWUMxIiwiZGVzaXJlZFJlcGxpY2F0aW9uQ291bnQiOjF9XSwidmVyc2lvbiI6MX0sIm1mYV9lbmFibGVkIjpmYWxzZSwic3RhdHVzIjoiQUNUSVZFIn0sImF1dGhlbnRpY2F0aW9uVHlwZSI6InNjb3BlZEtleSIsInNjb3BlZEtleUtleSI6Ijk2ZmUyNTE3MTViNTU4NGE0MTk1Iiwic2NvcGVkS2V5U2VjcmV0IjoiMWM1MjFiMDRiMjUyODM5MGU4MTkwNDU0NDk4MmYyNjJlMmZkY2JkNzc0YjI1YzI2YjQxM2RjM2VjODgzNzk1YSIsImlhdCI6MTY3NzQzNTY2N30.w8elVwSZ_U62af_MVKlVcawik9dQ-eLsoUVE4osqzlc"
export const pinataApiKey = "96fe251715b5584a4195"
export const pinataApiSecret = "1c521b04b2528390e81904544982f262e2fdcbd774b25c26b413dc3ec883795a"
18 changes: 17 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'

// https://vitejs.dev/config/
export default defineConfig({
// ...other config settings
plugins: [react()],
})
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true
})
]
}
}
})
Loading

0 comments on commit 513e65f

Please sign in to comment.