Skip to content

Commit

Permalink
New Connection Flow (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
nhenin authored Nov 3, 2023
1 parent f00816b commit d046912
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 308 deletions.
82 changes: 51 additions & 31 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
// App.tsx

import React, {useState} from 'react';
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import Landing from './Landing';

import ToastMessage from './ToastMessage';
import About from './vesting/About';
import YourTokenPlans from './vesting/Claimer';
import CreatePlans from './vesting/Provider';
import {About} from './vesting/About';
import Claimer from './vesting/Claimer';
import Provider from './vesting/Provider';
import { Footer } from './Footer';
import { ConnectionWallet } from './Connection';

type AppProps = {
runtimeURL: string;
marloweScanURL : string;
dAppId : string;
}

const App: React.FC<AppProps> = ({runtimeURL,marloweScanURL,dAppId}) => {
const hasSelectedAWalletExtension = localStorage.getItem('walletProvider');
type Page = "About" | "Token Provider's View" | "Claimer's View"

const aboutPage : Page = "About"
const isAboutPage = (page:Page) => page === aboutPage
const providerPage : Page = "Token Provider's View"
const isProviderPage = (page:Page) => page === providerPage
const claimerPage = "Claimer's View"
const isClaimerPage = (page:Page) => page === claimerPage

const App: React.FC<AppProps> = ({runtimeURL,marloweScanURL,dAppId}) => {
const [isWaitingConfirmation, setWaitingConfirmation] = useState(false);
const [isConnected, setIsConnected] = useState(false);
const [currentPage, setCurrentPage] = useState<Page>("About");
const [toasts, setToasts] = useState<any[]>([]);

const setAndShowToast = (title: string, message: React.ReactNode) => {
Expand All @@ -29,29 +39,39 @@ const App: React.FC<AppProps> = ({runtimeURL,marloweScanURL,dAppId}) => {
}

return (
<Router>
<Routes>
<Route path="/" element={hasSelectedAWalletExtension ? <Navigate to="/provider" /> : <Landing setAndShowToast={setAndShowToast} />} />
<Route path="/claimer" element={hasSelectedAWalletExtension ? <YourTokenPlans runtimeURL={runtimeURL} marloweScanURL={marloweScanURL} dAppId={dAppId} setAndShowToast={setAndShowToast} /> : <Navigate to="/" />} />
<Route path="/provider" element={hasSelectedAWalletExtension ? <CreatePlans runtimeURL={runtimeURL} marloweScanURL={marloweScanURL} dAppId={dAppId} setAndShowToast={setAndShowToast} /> : <Navigate to="/" />} />
<Route path="/about" element={hasSelectedAWalletExtension ? <About setAndShowToast={setAndShowToast} /> : <Navigate to="/" />} />
</Routes>
<div className="toast-container position-fixed bottom-0 end-0 p-3">
{toasts.map(toast => (
<ToastMessage
key={toast.id}
id={toast.id}
title={toast.title}
message={toast.message}
show={true}
isDanger={toast.isDanger}
onClose={() => removeToast(toast.id)}
/>
))}
</div>
</Router>

);
<div className="container">
<div className="header">
<div style={{width:"700px"}} className="d-flex justify-content-start align-items-baseline" >
<span ><h1 style={{margin:0}}>Token Plan Prototype</h1> </span>
<span ><h3 style={{margin:0,paddingLeft:"10px"}}>/ {currentPage}</h3> </span>
</div>
<ConnectionWallet onConnect={() => setIsConnected(true)} onDisconnect={() => {setCurrentPage(aboutPage);setIsConnected(false)}} runtimeURL={runtimeURL} setAndShowToast={setAndShowToast} />
</div>
<div> <button className="btn btn-link" disabled={isWaitingConfirmation || isAboutPage(currentPage)} onClick={() => setCurrentPage(aboutPage)}>{aboutPage}</button>
| <button className="btn btn-link" disabled={isWaitingConfirmation || !isConnected || isProviderPage(currentPage)} onClick={() => setCurrentPage(providerPage)}>{providerPage}</button>
| <button className="btn btn-link" disabled={isWaitingConfirmation || !isConnected || isClaimerPage(currentPage)} onClick={() => setCurrentPage(claimerPage)}>{claimerPage}</button>
<hr></hr>
</div>
{isAboutPage(currentPage)?
<About/>:(isProviderPage(currentPage)?
<Provider onWaitingConfirmation={() => setWaitingConfirmation(true) } onConfirmation={() => setWaitingConfirmation(false)} runtimeURL={runtimeURL} marloweScanURL={marloweScanURL} dAppId={dAppId} setAndShowToast={setAndShowToast} />
: <Claimer runtimeURL={runtimeURL} marloweScanURL={marloweScanURL} dAppId={dAppId} setAndShowToast={setAndShowToast} />
)}
<Footer />
<div className="toast-container position-fixed bottom-0 end-0 p-3">
{toasts.map(toast => (
<ToastMessage
key={toast.id}
id={toast.id}
title={toast.title}
message={toast.message}
show={true}
isDanger={toast.isDanger}
onClose={() => removeToast(toast.id)}
/>
))}
</div>
</div>);
};

export default App;
54 changes: 28 additions & 26 deletions src/components/Connection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,47 @@ import { BrowserRuntimeLifecycleOptions, mkRuntimeLifecycle } from '@marlowe.io/
import { mkRestClient } from '@marlowe.io/runtime-rest-client';
import { SupportedWalletName, getInstalledWalletExtensions } from '@marlowe.io/wallet/browser';
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Image } from 'semantic-ui-react'
import { SelectWalletExtensionModal } from './modals/SelectWalletExtension';

type ConnectionWalletProps = {
runtimeURL : string,
onConnect: () => void
onDisconnect: () => void
setAndShowToast: (title:string, message:any, isDanger: boolean) => void
};

type DisconnectedProps = {
runtimeURL : string,
setAndShowToast: (title:string, message:any, isDanger: boolean) => void
};

type ConnectedProps = {
runtimeURL : string,
onDisconnect: () => void
selectedWalletExtensionName : string
setAndShowToast: (title:string, message:any, isDanger: boolean) => void
};

export const ConnectionWallet: React.FC<ConnectionWalletProps> = ({runtimeURL,setAndShowToast}) => {
export const ConnectionWallet: React.FC<ConnectionWalletProps> = ({runtimeURL,setAndShowToast,onConnect,onDisconnect}) => {

const [showSelectWalletExtensionModal, setShowSelectWalletExtensionModal] = useState(false);
const selectedWalletExtensionName = localStorage.getItem('walletProvider');
if (!selectedWalletExtensionName) { return <DisconnectedWallet runtimeURL={runtimeURL} setAndShowToast={setAndShowToast} /> }
else { return <ConnectedWallet runtimeURL={runtimeURL} selectedWalletExtensionName={selectedWalletExtensionName} setAndShowToast={setAndShowToast} /> }
}

export const DisconnectedWallet: React.FC<DisconnectedProps> = ({runtimeURL}) => {

return <div>Connection</div>

if (!selectedWalletExtensionName) {
return (<><div className="dropdown" style={{width: "210px"}}>
<button className="btn btn-light btn-sm dropdown-toggle mr-2" onClick={() => setShowSelectWalletExtensionModal(true)}>
<span style={{fontSize: "medium"}}>
Connect Cardano Wallet
</span>
</button>
</div>
<SelectWalletExtensionModal
showModal={showSelectWalletExtensionModal}
onConnect={() => onConnect()}
closeModal={() => setShowSelectWalletExtensionModal(false) }
/></>)
}
else {
return <><ConnectedWallet onDisconnect={() => onDisconnect()} runtimeURL={runtimeURL} selectedWalletExtensionName={selectedWalletExtensionName} setAndShowToast={setAndShowToast}/>
</> }
}

export const ConnectedWallet : React.FC<ConnectedProps> = ({ runtimeURL,selectedWalletExtensionName,setAndShowToast }) => {
const navigate = useNavigate();
export const ConnectedWallet : React.FC<ConnectedProps> = ({ runtimeURL,selectedWalletExtensionName,setAndShowToast,onDisconnect }) => {
const [runtimeLifecycle, setRuntimeLifecycle] = useState<RuntimeLifecycle>();
const [changeAddress, setChangeAddress] = useState<string>('')
const [isMainnet, setIsMainnet] = useState<boolean>(false)
Expand All @@ -60,8 +68,8 @@ export const ConnectedWallet : React.FC<ConnectedProps> = ({ runtimeURL,selecte
fetchData()

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedWalletExtensionName, navigate]);

}, [selectedWalletExtensionName]);
const copyToClipboard = async () => {
try {
await navigator.clipboard.writeText(changeAddress);
Expand All @@ -77,13 +85,7 @@ export const ConnectedWallet : React.FC<ConnectedProps> = ({ runtimeURL,selecte

const disconnectWallet = () => {
localStorage.removeItem('walletProvider');

setAndShowToast(
'Disconnected wallet',
<span className='text-color-white'>Please, Connect a wallet to see your Token Plans.</span>,
false
);
navigate('/');
onDisconnect()
}

const adas = (Math.trunc(lovelaceBalance / 1_000_000))
Expand Down
82 changes: 0 additions & 82 deletions src/components/Landing.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions src/components/modals/NewVesting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ const NewVestingScheduleModal: React.FC<NewVestingScheduleModalProps> = ({ showM
<h5 className="modal-title">New Vesting Schedule</h5>
</div>
<div className='col-2 text-right'>
<button type="button" className="close btn btn-outline-secondary" onClick={handleClose}>
<span aria-hidden="true">&times;</span>
<button type="button" className="btn btn-outline-secondary" onClick={handleClose}>
<svg fill="none" height="15" viewBox="0 0 14 15" width="14" xmlns="http://www.w3.org/2000/svg" className="dark:text-gray-400"><path d="M13.6743 0.442879C13.2399 0.00862377 12.5358 0.00862377 12.1014 0.442879L7 5.54428L1.8986 0.442879C1.46422 0.00862377 0.760077 0.00862377 0.325691 0.442879C-0.108564 0.877265 -0.108564 1.5814 0.325691 2.01579L5.42709 7.11719L0.325691 12.2186C-0.108564 12.653 -0.108564 13.3571 0.325691 13.7915C0.760077 14.2258 1.46422 14.2258 1.8986 13.7915L7 8.6901L12.1014 13.7915C12.5358 14.2258 13.2399 14.2258 13.6743 13.7915C14.1086 13.3571 14.1086 12.653 13.6743 12.2186L8.57291 7.11719L13.6743 2.01579C14.1086 1.5814 14.1086 0.877265 13.6743 0.442879Z" fill="currentColor"></path></svg>
</button>
</div>
</div>
Expand Down
81 changes: 81 additions & 0 deletions src/components/modals/SelectWalletExtension.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { } from 'react';
import './modal.scss';
import "react-datepicker/dist/react-datepicker.css";
import { getInstalledWalletExtensions } from '@marlowe.io/wallet/browser';


interface SelectWalletExtensionModalProps {
showModal: boolean;
closeModal: () => void;
onConnect: () => void
}


export const SelectWalletExtensionModal: React.FC<SelectWalletExtensionModalProps> = ({ showModal, closeModal,onConnect}) => {

const installedWalletExtensions = getInstalledWalletExtensions()

async function connectWallet(walletName: string) {
localStorage.setItem('walletProvider', walletName);
onConnect();
closeModal()
}

function capitalizeFirstLetter(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1);
}

return (
<>
<div className={`modal ${showModal ? 'show' : ''}`} tabIndex={1} style={{ display: showModal ? 'block' : 'none' }}>
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-header" style={{border:"none"}}>
<div className='container'>
<div className='row'>
<div className='col-10 text-left'>
<h2 className="modal-title">Connnect to Wallet</h2>
</div>
<div className='col-2 text-right'>
<button type="button" className="btn btn-outline-secondary" onClick={() => closeModal()}>
<svg fill="none" height="15" viewBox="0 0 14 15" width="14" xmlns="http://www.w3.org/2000/svg" className="dark:text-gray-400"><path d="M13.6743 0.442879C13.2399 0.00862377 12.5358 0.00862377 12.1014 0.442879L7 5.54428L1.8986 0.442879C1.46422 0.00862377 0.760077 0.00862377 0.325691 0.442879C-0.108564 0.877265 -0.108564 1.5814 0.325691 2.01579L5.42709 7.11719L0.325691 12.2186C-0.108564 12.653 -0.108564 13.3571 0.325691 13.7915C0.760077 14.2258 1.46422 14.2258 1.8986 13.7915L7 8.6901L12.1014 13.7915C12.5358 14.2258 13.2399 14.2258 13.6743 13.7915C14.1086 13.3571 14.1086 12.653 13.6743 12.2186L8.57291 7.11719L13.6743 2.01579C14.1086 1.5814 14.1086 0.877265 13.6743 0.442879Z" fill="currentColor"></path></svg>
</button>
</div>
</div>
</div>
</div>
<div className="modal-body">
<div className="card-body">
{installedWalletExtensions.map(extension =>
<div key={extension.name} className="card_WrXe" style={{fontFamily:"inter"}} onClick={() => connectWallet(extension.name)}>
<div key={extension.name+".title"} className="d-flex justify-content-start align-items-center">
<img src={extension.icon} alt="Icon Before" width="20px" height="20px" style={{marginRight:"5px"}} />
<span style={{textAlign:"left",fontSize:"1.1rem"}}>{capitalizeFirstLetter(extension.name)}</span>
</div>
<div key={extension.name+".supports"} className="d-flex justify-content-start align-items-center">
{extension.supported?
<p style={{textAlign:"left",fontSize:"x-small",marginTop:"10px"}}>(Supports Marlowe Technology)</p>
: <p style={{textAlign:"left",fontSize:"x-small",marginTop:"10px"}}>(May not support Marlowe Technology)</p>
}
</div>
<div key={extension.name+".connect"} className="d-flex justify-content-end align-items-center">
<span style={{fontSize:"small",color: "var(--ifm-link-color)"}}> Connect </span>
<svg width="12"
height="12" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"
className="arrow"><path d="M3 8h9M8.168 12.5l4.5-4.5-4.5-4.5" stroke="#1B2738"
strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"></path></svg>
</div>
</div>
)}
</div>
</div>


</div>
</div>
</div>
{showModal && <div className="modal-backdrop show"></div>}
</>
);
};

11 changes: 7 additions & 4 deletions src/components/modals/modal.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
.modal-title {
color: var(--button-contract-tab-default, #878FAA);
font-family: Outfit;
font-size: 1.625rem;

font-family: Inter;
color:rgb(135, 143, 170);
font-size: 1.325rem;
font-style: normal;
font-weight: 700;
margin: 0;
padding: 0;
font-weight: 400;
line-height: normal;
}
.modal-header, .modal-footer {
Expand Down
Loading

0 comments on commit d046912

Please sign in to comment.