Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 58 additions & 89 deletions src/features/common/components/add-issue-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,60 @@
import FormInput from "./form-input"


import { AiOutlineClose } from "react-icons/ai"
import { useState } from "react";
import Button from "./button";

import { useWalletSignedInAccountQuery } from "../hooks/useWalletQueries";

import { useUser } from '@auth0/nextjs-auth0'

import { useAccount } from 'wagmi'
import axios from "axios";

type AddIssueModalProps = {
setIsModalOpen: (value: boolean) => void
import Modal from "./modal";
import { useCreateSuggestion } from "../hooks/useGuildQueries";

export default function AddIssueModal({
isOpen,
setIsOpen,
}: {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
}) {
const [value, setValue] = useState("");
const { mutate: createSuggestion, isLoading } = useCreateSuggestion();

const handleSubmit = () => {
if (!value.trim()) return;
createSuggestion(
{ suggestion: value },
{
onSuccess: () => {
setValue("");
setIsOpen(false);
},
}
);
};

return (
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} title="Suggest a feature">
<div
style={{
display: "flex",
flexDirection: "column",
height: "100%",
}}
className="rounded-md p-4 bg-white dark:bg-zinc-900 flex flex-col dark:text-white text-gray-900 w-[90vw] h-[80vh] lg:w-[50vw]"
>
<h2 className="text-xl font-bold mb-2 dark:text-white text-gray-900">
Feature Request
</h2>
<p className="text-sm dark:text-gray-400 text-gray-500 mb-4">
Describe the feature you would like to see.
</p>
<textarea
className="mt-4 resize-none h-[70%] bg-gray-100 dark:bg-zinc-700 px-4 py-2 rounded-md mb-4 dark:text-white text-gray-900 placeholder-gray-400 dark:placeholder-gray-500"
placeholder="Drop your suggestions here. After submitting, tag the issue with >open< and >feature< to mirror it on this page for voting and funding"
onChange={(e) => setValue(e.target.value)}
value={value}
/>
<button
onClick={handleSubmit}
disabled={isLoading || !value.trim()}
className="px-4 py-2 bg-lime-500 dark:bg-lime-600 text-white rounded-md hover:bg-lime-600 dark:hover:bg-lime-700 disabled:opacity-50 disabled:cursor-not-allowed"
>
{isLoading ? "Submitting..." : "Submit"}
</button>
</div>
</Modal>
);
}

const AddIssueModal = ({ setIsModalOpen }: AddIssueModalProps) => {
const [value, setValue] = useState("");
const [title, setTitle] = useState("")
const walletId = useWalletSignedInAccountQuery()
const { user, error, isLoading } = useUser();
const { address } = useAccount()
const [isSubmitLoading, setIsLoading] = useState(false)


const getWalletId = () => {
const walletChain = localStorage.getItem("wallet-chain")

let connectedWalletId;

if (walletChain === "near") {
connectedWalletId = walletId
} else if (walletChain === "polygon") {
connectedWalletId = address
} else {
connectedWalletId = "Unknown"
}

return connectedWalletId
}

const submitIssue = async () => {
if (title.length === 0 || value.length == 0 || isSubmitLoading) return
setIsLoading(true);
try {
let isGithubAuth = user != undefined
let userId = user ? user?.sub : getWalletId()

const result = await axios.post("/api/issues/addIssue", {
userId,
title,
body: value, isGithubAuth
}) as any

const url = await result?.data?.message?.html_url

window.open(url, "_blank")
setIsLoading(false);
setIsModalOpen(false)
} catch (e) {
setIsLoading(false);

console.log(e)
}

}

return <div onClick={() => setIsModalOpen(false)} className="w-screen h-screen bg-black/50 top-0 left-0 absolute z-10 flex items-center justify-center">
<div onClick={(e) => {
e.stopPropagation()
}} className="rounded-md p-4 bg-white dark:bg-zinc-900 flex flex-col dark:text-white w-[90vw] h-[80vh] lg:w-[50vw] ">
<div className="flex items-center justify-between">

<span className="font-bold mb-4">Add Issue</span>
<AiOutlineClose className="text-[1.5rem] cursor-pointer" onClick={() => setIsModalOpen(false)} />
</div>
<FormInput onChange={(e) => setTitle(e.target?.value)} placeholder="Issue Title" />

<textarea className="mt-4 resize-none h-[70%] bg-gray-200 dark:bg-zinc-700 px-4 py-2 rounded-md mb-4" placeholder="Drop your suggestions here. After submitting, tag the issue with >open< and >feature< to mirror it on this page for voting and funding" onChange={(e) => setValue(e.target.value)} />

<Button onClick={submitIssue} disabled={title.length === 0 || value.length == 0} >
{isSubmitLoading ? "Loading..." : "Submit"}
</Button>
</div>
</div>
}


export default AddIssueModal
44 changes: 22 additions & 22 deletions src/features/common/components/button.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import React from "react";
import { ReactNode } from "react";

const typeToClass: Record<string, string> = {
const variants = {
primary:
"px-4 py-2 bg-pink-500 text-white shadow-lg shadow-pink-500/40 hover:brightness-150",
"flex flex-row items-center px-4 py-2 border-0 border-lime-500 dark:border-lime-600 bg-transparent text-lime-600 dark:text-lime-600 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
secondary:
"px-4 py-2 border-2 border-pink-500 bg-transparent text-pink-500 hover:brightness-150",
"flex flex-row items-center px-4 py-2 border-0 border-gray-200 dark:border-stone-500 bg-transparent text-gray-600 dark:text-gray-300 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
iconConnect:
"flex flex-row items-center px-4 py-2 border-0 border-lime-500 dark:border-lime-600 bg-transparent text-lime-500 dark:text-lime-600 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
"flex flex-row items-center px-4 py-2 border-0 border-lime-500 dark:border-lime-600 bg-transparent text-lime-600 dark:text-lime-600 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
iconDisconnect:
"flex flex-row items-center px-4 py-2 border-0 border-gray-200 dark:border-stone-500 bg-transparent text-gray-500 dark:text-gray-300 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
icon:
"flex flex-row items-center space-x-2 px-4 py-2 bg-pink-500 text-white shadow-lg shadow-pink-500/40 hover:brightness-150",
"flex flex-row items-center px-4 py-2 border-0 border-gray-300 dark:border-stone-500 bg-transparent text-gray-600 dark:text-gray-300 dark:hover:bg-zinc-800 hover:bg-gray-200 text-sm space-x-2",
};

export default function Button(
props: {
type?: "primary" | "secondary" | "inverse" | "iconConnect" | "iconDisconnect" | "icon";
} & React.HTMLProps<HTMLButtonElement>
) {
const { type = "primary", className = "", ...restProps } = props;

const baseClassName =
"rounded-md cursor-pointer disabled:brightness-50 hover:disabled:cursor-not-allowed";
const typeClassName = typeToClass[type];

export default function Button({
children,
type,
onClick,
className = "",
}: {
children: ReactNode;
type: keyof typeof variants;
onClick?: () => void;
className?: string;
}) {
return (
<button
className={`${className} ${baseClassName} ${typeClassName}`}
{...restProps}
/>
className={`${variants[type]} ${className}`}
onClick={onClick}
>
{children}
</button>
);
}
30 changes: 14 additions & 16 deletions src/features/common/components/chain-list-item.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import Image from "next/image";

import ChainIcon from "./chain-icon";

export default function ChainListItem(props: {
chainName: string;
onClick: (chainName: string) => void;
export default function ChainListItem({
name,
icon,
onClick,
}: {
name: string;
icon: JSX.Element;
onClick: () => void;
}) {
return (
<li
className="flex flex-row items-center p-2 mt-2 rounded-lg cursor-pointer hover:bg-black hover:bg-opacity-30 text-black dark:text-white"
onClick={() => props.onClick(props.chainName)}
<div
onClick={onClick}
className="flex flex-row items-center p-2 mt-2 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-black dark:hover:bg-opacity-30 text-gray-900 dark:text-white"
>
<ChainIcon
chainName={props.chainName}
className="dark:fill-current dark:text-white"
/>
<div className="ml-4">{props.chainName.toUpperCase()}</div>
</li>
<div className="mr-2 dark:fill-current dark:text-white">{icon}</div>
{name}
</div>
);
}
90 changes: 20 additions & 70 deletions src/features/common/components/connect-wallet-button.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,28 @@
import React from "react";
import { useRouter } from "next/router";
import Button from "./button";
import SelectChainModal from "./select-chain-modal";
import { useWalletChainQuery } from "../hooks/useWalletQueries";
import ChainIcon from "./chain-icon";

import {
useWalletChainQuery,
useWalletSignedInAccountQuery,
useWalletSignInMutation,
useWalletSignOutMutation,
} from "../hooks/useWalletQueries";
import config from "config";

export default function ConnectWalletButton() {
const router = useRouter();

const [isSelectChainModalOpen, setIsSelectChainModalOpen] =
React.useState(false);

const walletChainQuery = useWalletChainQuery();
const signedInAccountQuery = useWalletSignedInAccountQuery();
const signInMutation = useWalletSignInMutation();
const signOutMutation = useWalletSignOutMutation();

async function handleSelectChain(chain: string) {
signInMutation.mutate(chain);
}

async function handleDisconnectWallet() {
let path = window.location.pathname;
if (path.includes("add-bounty")) {
router.replace(`/issues/${path.split("/")[2]}`);
}

setTimeout(() => {
signOutMutation.mutate();
}, 1000);
}

if (walletChainQuery.data && signedInAccountQuery.data) {
return (
<div className="flex flex-row items-center">
<Button type="iconDisconnect" onClick={handleDisconnectWallet}>
<ChainIcon
size={20}
chainName={walletChainQuery.data}
className="dark:fill-gray-300 fill-gray-500 w-4 h-4"
/>
<div>{signedInAccountQuery.data}</div>
<svg className="dark:stroke-gray-300 stroke-gray-500" width="10" height="20" viewBox="0 0 10 24">
<path d="M9 1L1 9" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1 1L9 9" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</Button>
</div>
);
}
const { data: walletChain, isLoading } = useWalletChainQuery();

return (
<>
<Button type="iconConnect" onClick={() => setIsSelectChainModalOpen(true)}>
<svg className="stroke-current w-4 h-4" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 1H17C17.5304 1 18.0391 1.21071 18.4142 1.58579C18.7893 1.96086 19 2.46957 19 3V17C19 17.5304 18.7893 18.0391 18.4142 18.4142C18.0391 18.7893 17.5304 19 17 19H13" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M8 15L13 10L8 5" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13 10H1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<span>Connect Wallet</span>
</Button>
<SelectChainModal
isOpen={isSelectChainModalOpen}
onClose={() => setIsSelectChainModalOpen(false)}
onSelectChain={handleSelectChain}
enabledChains={config.site.enabledChains}
<button
className="flex flex-row items-center px-4 py-2 border border-lime-500 dark:border-lime-600 rounded-lg text-lime-600 dark:text-lime-600 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick={() => {
// Handle wallet connection
}}
>
<ChainIcon
size={20}
chainName={walletChain || ""}
className="dark:fill-gray-300 fill-gray-500 w-4 h-4"
/>
</>
<span className="ml-2 text-sm">
{isLoading ? "Loading..." : walletChain ? `Connected: ${walletChain}` : "Connect Wallet"}
</span>
<svg className="dark:stroke-gray-300 stroke-gray-500 ml-2" width="10" height="20" viewBox="0 0 10 24">
<path d="M9 1L1 9" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M1 1L9 9" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</button>
);
}
13 changes: 6 additions & 7 deletions src/features/common/components/form-input.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";

export default function FormInput(props: React.HTMLProps<HTMLInputElement>) {
const { className = "", ...restProps } = props;

export default function FormInput({
className = "",
...props
}: React.InputHTMLAttributes<HTMLInputElement>) {
return (
<input
className={`bg-gray-200 dark:bg-zinc-700 px-4 py-2 rounded-md ${className}`}
{...restProps}
{...props}
className={`bg-gray-100 dark:bg-zinc-700 px-4 py-2 rounded-md dark:text-white text-gray-900 placeholder-gray-400 dark:placeholder-gray-500 ${className}`}
/>
);
}
Loading