Skip to content

Commit

Permalink
Merge pull request #7 from hollow-leaf/feat/addPrepareVote
Browse files Browse the repository at this point in the history
Feat/add prepare vote
  • Loading branch information
yeeetai authored Aug 22, 2023
2 parents 8fe5fe4 + 64f0f85 commit 21832a3
Show file tree
Hide file tree
Showing 18 changed files with 502 additions and 37 deletions.
3 changes: 3 additions & 0 deletions apps/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module.exports = {
output: 'export',
reactStrictMode: true,
assetPrefix: './',
images: {
unoptimized: true
},
webpack: config => {
config.resolve.fallback = { fs: false, net: false, tls: false };
return config;
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"react-dom": "^18.2.0",
"react-webcam": "^7.1.1",
"ui": "workspace:*",
"helper": "workspace:*",
"viem": "^1.6.0",
"wagmi": "^1.3.10"
},
Expand Down
54 changes: 54 additions & 0 deletions apps/web/public/Kamui.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion apps/web/src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const metadata: Metadata = {

export default function Home() {
return (
<div className="flex flex-col items-center justify-center" style={{ height: 'calc(100vh - 216px)' }}>
<div className="flex flex-col items-center justify-center">
<main className="mx-auto w-auto px-4 pt-16 pb-8 sm:pt-24 lg:px-8">
<h1 className="mx-auto text-center text-6xl font-extrabold tracking-tight text-white sm:text-7xl lg:text-8xl xl:text-8xl">
Tobi
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<html lang="en" className="bg-zinc-900">
<html lang="en">
<body className="overflow-hidden">
<WagmiProvider>
<ClientOnly>
<Header />
</ClientOnly>
<div className="grow bg-cat-base overflow-y-auto" >{children}</div>
<div className="grow bg-cat-base overflow-y-auto" style={{ height: 'calc(100vh - 108px)' }}>{children}</div>
</WagmiProvider>
</body>
</html>
Expand Down
129 changes: 125 additions & 4 deletions apps/web/src/app/vote/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,130 @@
'use client'

import WebcamCapture from '../../components/Webcam/WebcamCapture'
import ProcessDialog from '../../components/Dialog/ProcessDialog'
import GenerateProof from '../../components/ZK/GenerateProof'
import VerifyProof from '../../components/ZK/VerifyProof'
import ProcessLoading from '../../components/Loading/ProcessLoading'
import KamuiLoading from '../../components/Loading/KamuiLoading'
import { useEffect, useState } from 'react'
import { useAccount } from 'wagmi'

export default function Vote() {
const [isLoading, setIsLoading] = useState(false);
const [isKamuiLoading, setIsKamuiLoading] = useState(false);
const { address, isConnected } = useAccount()
const [mounted, setMounted] = useState(false)
const [isCaptureDialogOpen, setIsCaptureDialogOpen] = useState(false)
const [isVerifyDialogOpen, setIsVerifyDialogOpen] = useState(false)
const [isGenProofDialogOpen, setIsGenProofDialogOpen] = useState(false)
const [isVerified, setVerified] = useState(false)
const [imgSrc, setImgSrc] = useState(null)
const [copied, setCopied] = useState(false)

async function openCaptureDialog() {
setIsCaptureDialogOpen(!isCaptureDialogOpen)
}

async function openGenProofDialog() {
setIsGenProofDialogOpen(!isGenProofDialogOpen)
}

async function openVerifyDialog() {
setIsVerifyDialogOpen(!isVerifyDialogOpen)
}

const handleCopyClick = () => {
setCopied(true)
setTimeout(() => {
setCopied(false)
}, 1000)
}

useEffect(() => {
if (isConnected) {
setMounted(true)
} else {
setMounted(false)
}
}, [address, isConnected])

return (
<div className="flex flex-col items-center justify-center" style={{ height: 'calc(100vh - 216px)' }}>
<WebcamCapture />
</div>
);
<div className='flex items-center justify-center'>
<div className='mx-auto w-full px-8 pt-8 pb-8'>
<div className='flex-col'>
<div className='flex flex-row space-x-3 items-center'>
<p className='font-mono text-black font-bold text-3xl dark:text-white my-4'>
Account Status
</p>
{isVerified
? <div className='badge badge-accent'>Verified</div>
: <div className='badge badge-secondary'>Unverified</div>
}
</div>
<div className='flex flex-row py-2 space-x-11 justify-center'>
<div className='flex flex-col items-center space-y-5'>
<span className='font-mono'>1. Capture your face for KYC</span>
<div className='bg-gradient-to-r from-[#42275a] to-[#734b6d] card w-[350px] p-4 text-white shadow-[0_3px_10px_rgb(0,0,0,0.2)]'>
<div className='btn btn-ghost' onClick={openCaptureDialog}>Capture face</div>
</div>
</div>
<div className='flex flex-col items-center space-y-5'>
<span className='font-mono'>2. Check your face to generate proof</span>
<div className='bg-gradient-to-r from-[#42275a] to-[#734b6d] card w-[350px] p-4 text-white shadow-[0_3px_10px_rgb(0,0,0,0.2)]'>
{
imgSrc
? <div className='btn btn-ghost' onClick={openGenProofDialog}>Generate Proof</div>
: <div className='btn btn-ghost' onClick={openCaptureDialog}>Need to capture face first</div>
}
</div>
</div>
<div className='flex flex-col items-center space-y-5'>
<span className='font-mono'>3. Input Proof to KYC</span>
<div className='bg-gradient-to-r from-[#42275a] to-[#734b6d] card w-[350px] p-4 text-white shadow-[0_3px_10px_rgb(0,0,0,0.2)]'>
<div className='btn btn-ghost' onClick={openVerifyDialog}>Verify Proof</div>
</div>
</div>
</div>
<div className='divider'></div>

<p className='font-mono text-black font-bold text-3xl mb-4 dark:text-white'>
Proposal
</p>
</div>
<ProcessDialog
isOpen={isCaptureDialogOpen}
onClose={() => setIsCaptureDialogOpen(false)}
title={'Capture Face'}
>
<WebcamCapture setImgSrc={setImgSrc} onClose={() => setIsCaptureDialogOpen(false)} />
</ProcessDialog>
<ProcessDialog
isOpen={isGenProofDialogOpen}
onClose={() => setIsGenProofDialogOpen(false)}
title={'Generate proof'}
>
<GenerateProof imgSrc={imgSrc} handleCopyClick={handleCopyClick} setIsLoading={setIsLoading} onClose={() => setIsGenProofDialogOpen(false)} />
</ProcessDialog>
<ProcessDialog
isOpen={isVerifyDialogOpen}
onClose={() => setIsVerifyDialogOpen(false)}
title={'Verify proof'}
>
<VerifyProof setVerified={setVerified} setIsLoading={setIsLoading} onClose={() => setIsVerifyDialogOpen(false)} />
</ProcessDialog>
{isLoading && <ProcessLoading />}
{isKamuiLoading && <KamuiLoading />}
{
copied &&
<div className='toast toast-top toast-end'>
<div className='alert alert-success'>
<span>Copied to clipboard</span>
</div>
</div>
}
</div>

</div >

)
}
25 changes: 25 additions & 0 deletions apps/web/src/components/Dialog/ProcessDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export interface ProcessDialogProps {
isOpen: boolean
onClose: any
title: any
children: any
}
const ProcessDialog = ({...props}: ProcessDialogProps) => {
if(!props.isOpen) return null

return(
<div className="fixed inset-0 flex flex-col items-center justify-center">
<div className="rounded-lg bg-gradient-to-r from-[#42275a] to-[#734b6d] card p-4 text-white shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
<div className="flex flex-row mb-2 items-center">
<span className="font-mono text-black font-bold text-lg dark:text-white w-full">{props.title}</span>
<svg className="btn btn-sm btn-circle btn-ghost justify-center rounded-full w-8 h-6" onClick={()=>props.onClose()} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</div>
{props.children}
</div>
</div>
)
}

export default ProcessDialog
14 changes: 14 additions & 0 deletions apps/web/src/components/Loading/KamuiLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Image from 'next/image'


const KamuiLoading = (() => {

return (
<div className='flex flex-col items-center justify-center space-y-4'>
<Image src="/Kamui.svg" alt='Sharingan' className='w-40 h-40 animate-spin' width={500} height={500} />
<span className='text-cat-peach400 text-lg'>Kamuiing...</span>
</div>
)

})
export default KamuiLoading
13 changes: 13 additions & 0 deletions apps/web/src/components/Loading/ProcessLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Image from 'next/image'


const ProcessLoading = (() => {

return (
<div className='flex flex-col items-center justify-center space-y-4'>
<span className="loading loading-spinner loading-lg w-100"></span>
</div>
)

})
export default ProcessLoading
32 changes: 18 additions & 14 deletions apps/web/src/components/NavBar/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@

import React from 'react'
import Link from 'next/link'
import { ConnectKitButton } from "connectkit"
import { ConnectKitButton } from 'connectkit'
import Image from 'next/image'


const Header: React.FC = () => {
return (
<header className="bg-cat-crust p-4 flex items-center justify-between ">
<div className="navbar bg-base-500">
<div className="navbar-start">
<img
src="/tobi.png" // 替換成你的圖標的路徑
alt="Icon"
className="w-14 h-14"
/>
<ul className="menu menu-horizontal px-1 text-xl lg:flex">
<li><Link href={"/dashboard"}>Dashboard</Link></li>
<li><Link href={"/bind"}>Bind</Link></li>
<li><Link href={"/vote"}>Vote</Link></li>
<header className='bg-cat-crust p-4 flex items-center justify-between '>
<div className='navbar bg-base-500'>
<div className='navbar-start'>
<Link href={'/home'}>
<Image
alt='Tobi'
src='/tobi.png'
width={500}
height={500}
className='w-14 h-14'
/>
</Link>
<ul className='menu menu-horizontal px-1 text-xl lg:flex'>
<li><Link href={'/home'}>Home</Link></li>
<li><Link href={'/vote'}>Vote</Link></li>
</ul>
</div>
<div className="navbar-end mr-5">
<div className='navbar-end mr-5'>
<div>
<ConnectKitButton />
</div>
Expand Down
5 changes: 1 addition & 4 deletions apps/web/src/components/Provider/WagmiProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Chain, configureChains, createConfig, WagmiConfig } from 'wagmi'
import { goerli, polygonMumbai, sepolia } from 'wagmi/chains'
import { ConnectKitProvider, getDefaultConfig } from "connectkit"
import { publicProvider } from 'wagmi/providers/public'
import * as React from 'react';

const defaultChains: Chain[] = [
goerli,
Expand All @@ -31,12 +30,10 @@ const config = createConfig(
);

export const WagmiProvider = ({ children }: { children: React.ReactNode }) => {
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
return (
<WagmiConfig config={config}>
<ConnectKitProvider>
{mounted && children}
{children}
</ConnectKitProvider>
</WagmiConfig>
)
Expand Down
47 changes: 35 additions & 12 deletions apps/web/src/components/Webcam/WebcamCapture.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,50 @@
'use client'

import Webcam from "react-webcam";
import React, { useRef, useState, useCallback } from 'react';
import React, { useRef, useState, useCallback, useEffect } from 'react';
import {sleep} from 'helper'

export interface WebcamCaptureProps {
setImgSrc: any
onClose: any
}

const WebcamCapture = () => {
const WebcamCapture = ({setImgSrc, onClose}: WebcamCaptureProps) => {
const webcamRef = useRef<Webcam>(null)
const [imgSrc, setImgSrc] = useState(null);
const [imgSrc, setWebcamImg] = useState(null)

const capture = useCallback(() => {
const imageSrc = webcamRef.current.getScreenshot();
setImgSrc(imageSrc);
setWebcamImg(imageSrc)
setImgSrc(imageSrc)
}, [webcamRef, setImgSrc]);

const retryCapture = () => {
setWebcamImg(null)
setImgSrc(null)
}

return (
<div className="container">
<Webcam height={600} width={600} ref={webcamRef} mirrored={true} />
<div className="btn" onClick={capture} >Capture</div>
{imgSrc && (
<img
src={imgSrc}
/>
)}
<div className="flex flex-col items-center ">
<div className="pb-4">
{
imgSrc
? <img src={imgSrc} alt="webcam"/>
: <Webcam height={500} width={500} ref={webcamRef} mirrored={true} />
}
</div>
<div className="flex flex-row space-x-3">
{
imgSrc
? <div className="btn" onClick={retryCapture} >Recapture</div>
: <div className="btn" onClick={capture} >Capture</div>
}
{
imgSrc
? <div className="btn" onClick={onClose} >OK</div>
: null
}
</div>
</div>
);
}
Expand Down
Loading

0 comments on commit 21832a3

Please sign in to comment.