Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Database staging update to prod #436

Merged
merged 7 commits into from
Dec 23, 2024
Merged
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
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ model Bounties {
title String
description String
amount String
amount_sort Float
issuer String
in_progress Boolean? @default(true)
is_joined_bounty Boolean? @default(false)
Expand Down
41 changes: 35 additions & 6 deletions src/app/[netname]/bounty/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,50 @@
'use client';
import * as React from 'react';
import { ToastContainer } from 'react-toastify';

import 'react-toastify/dist/ReactToastify.css';

import React, { useState } from 'react';
import BountyClaims from '@/components/bounty/BountyClaims';
import BountyInfo from '@/components/bounty/BountyInfo';
import CreateClaim from '@/components/ui/CreateClaim';
import NavBarMobile from '@/components/global/NavBarMobile';
import { useScreenSize } from '@/hooks/useScreenSize';
import { useSearchParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import { trpc, trpcClient } from '@/trpc/client';
import { useGetChain } from '@/hooks/useGetChain';
import Loading from '@/components/global/Loading';

export default function Bounty({ params }: { params: { id: string } }) {
const chain = useGetChain();
const searchParams = useSearchParams();
const isMobile = useScreenSize();
const utils = trpc.useUtils();
const [status, setStatus] = useState('Indexing…');

const indexingMutation = useQuery({
queryKey: ['indexing'],
queryFn: async () => {
setStatus('Indexing 1s');
for (let i = 0; i < 60; i++) {
setStatus(`Indexing ${i}s`);
const bounty = await trpcClient.isBountyCreated.query({
id: Number(params.id),
chainId: chain.id,
});

if (bounty) {
utils.bounty.invalidate();
return;
}

await new Promise((resolve) => setTimeout(resolve, 1_000));
}

throw new Error('Failed to index bounty');
},
enabled: searchParams.get('indexing') === 'true',
});

return (
<>
<Loading open={indexingMutation.isLoading} status={status} />
<div className='px-5 lg:px-20'>
<BountyInfo bountyId={params.id} />
<BountyClaims bountyId={params.id} />
Expand All @@ -24,7 +54,6 @@ export default function Bounty({ params }: { params: { id: string } }) {
) : (
<CreateClaim bountyId={params.id} />
)}
<ToastContainer />
<div className='h-80' />
</>
);
Expand Down
5 changes: 0 additions & 5 deletions src/app/[netname]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
'use client';

import React from 'react';
import { ToastContainer } from 'react-toastify';

import 'react-toastify/dist/ReactToastify.css';

import ContentHome from '@/components/layout/ContentHome';
import NavBarMobile from '@/components/global/NavBarMobile';
import CreateBounty from '@/components/ui/CreateBounty';
Expand All @@ -17,7 +13,6 @@ export default function Home() {
<>
<ContentHome />
{isMobile ? <NavBarMobile type='bounty' /> : <CreateBounty />}
<ToastContainer />
</>
);
}
3 changes: 3 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import '@/styles/globals.css';
import '@/styles/colors.css';
import 'react-toastify/dist/ReactToastify.css';
import { headers } from 'next/headers';
import React from 'react';
import { TRPCProvider } from '@/trpc/client';
import Header from '@/components/layout/Header';
import '@rainbow-me/rainbowkit/styles.css';
import { WalletProvider } from '@/components/global/WalletProvider';
import { ToastContainer } from 'react-toastify';

export const metadata = {
title: "poidh - pics or it didn't happen",
Expand All @@ -28,6 +30,7 @@ const RootLayout = async ({ children }: { children: React.ReactNode }) => {
<WalletProvider>
<Header />
{children}
<ToastContainer />
</WalletProvider>
</TRPCProvider>
</body>
Expand Down
2 changes: 0 additions & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import { NetworkSelector } from '@/components/global/NetworkSelector';
import * as React from 'react';

import 'react-toastify/dist/ReactToastify.css';

const Home = () => {
return (
<div className='flex flex-col items-center justify-center text-center p-6 min-h-[85vh]'>
Expand Down
2 changes: 1 addition & 1 deletion src/components/bounty/BountyClaims.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function BountyClaims({ bountyId }: { bountyId: string }) {
);

if (!claims) {
return null;
return <div className=''>No claims</div>;
}

return (
Expand Down
6 changes: 6 additions & 0 deletions src/components/bounty/BountyInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export default function BountyInfo({ bountyId }: { bountyId: string }) {

const signMutation = useMutation({
mutationFn: async (bountyId: string) => {
//arbitrum has a problem with message signing, so all confirmations are on base
const chainId = await account.connector?.getChainId();
if (chainId !== 8453) {
await switctChain.switchChainAsync({ chainId: 8453 });
}

const message =
getBanSignatureFirstLine({
id: Number(bountyId),
Expand Down
5 changes: 5 additions & 0 deletions src/components/bounty/ClaimItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export default function ClaimItem({

const signMutation = useMutation({
mutationFn: async (claimId: string) => {
const chainId = await account.connector?.getChainId();
if (chainId !== 8453) {
//arbitrum has a problem with message signing, so all confirmations are on base
await switctChain.switchChainAsync({ chainId: 8453 });
}
const message = getBanSignatureFirstLine({
id: Number(claimId),
chainId: chain.id,
Expand Down
20 changes: 2 additions & 18 deletions src/components/global/FormBounty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { decodeEventLog, parseEther } from 'viem';
import abi from '@/constant/abi/abi';
import { cn } from '@/utils';
import Loading from '@/components/global/Loading';
import { trpcClient } from '@/trpc/client';
import GameButton from '@/components/global/GameButton';
import ButtonCTA from '@/components/ui/ButtonCTA';
import { InfoIcon } from '@/components/global/Icons';
Expand Down Expand Up @@ -83,25 +82,10 @@ export default function FormBounty({
throw new Error('Invalid event: ' + data.eventName);
}

const bountyId = data.args.id.toString();

for (let i = 0; i < 60; i++) {
setStatus('Indexing ' + i + 's');
const bounty = await trpcClient.isBountyCreated.query({
id: Number(bountyId),
chainId: chain.id,
});

if (bounty) {
return bountyId;
}
await new Promise((resolve) => setTimeout(resolve, 1_000));
}

throw new Error('Failed to index bounty');
return data.args.id.toString();
},
onSuccess: (bountyId) => {
router.push(`/${chain.slug}/bounty/${bountyId}`);
router.push(`/${chain.slug}/bounty/${bountyId}?indexing=true`);
toast.success('Bounty created successfully');
},
onError: (error) => {
Expand Down
26 changes: 26 additions & 0 deletions src/components/global/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,29 @@ export function CloseIcon({
</svg>
);
}

export function SortIcon({
width = 24,
height = 24,
}: {
width?: number;
height?: number;
}) {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 22'
strokeWidth={1.5}
stroke='#fff'
width={width}
height={height}
>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M3 7.5 7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5'
/>
</svg>
);
}
117 changes: 88 additions & 29 deletions src/components/layout/ContentHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import { useGetChain } from '@/hooks/useGetChain';
import { trpc } from '@/trpc/client';
import BountyList from '@/components/ui/BountyList';
import { cn } from '@/utils';
import { FormControl, MenuItem, Select } from '@mui/material';
import { SortIcon } from '@/components/global/Icons';

type DisplayType = 'open' | 'progress' | 'past';
type SortType = 'value' | 'id';

export default function ContentHome() {
const [display, setDisplay] = useState<DisplayType>('open');
const [sortType, setSortType] = useState<SortType>('id');
const chain = useGetChain();

const bounties = trpc.bounties.useInfiniteQuery(
{
chainId: chain.id,
status: display,
limit: 6,
sortType,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
Expand All @@ -26,36 +31,90 @@ export default function ContentHome() {

return (
<>
<div className='z-1 flex flex-nowrap container mx-auto border-b border-white py-12 w-full justify-center gap-2 px-8'>
<div
className={cn(
'flex flex-nowrap border border-white rounded-full transition-all bg-gradient-to-r',
'md:text-base sm:text-sm text-xs',
display == 'open' && 'from-red-500 to-40%',
display == 'progress' &&
'via-red-500 from-transparent to-transparent from-[23.33%] to-[76.66%]',
display == 'past' && 'from-transparent from-60% to-red-500',
'gap-2 md:gap-4'
)}
>
<button
onClick={() => setDisplay('open')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 py-2'
>
new bounties
</button>
<button
onClick={() => setDisplay('progress')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 py-2'
>
voting in progress
</button>
<button
onClick={() => setDisplay('past')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 py-2'
<div className='z-1 flex flex-wrap container mx-auto border-b border-white hover:border-white py-6 md:py-12 sm:py-8 w-full items-center px-8'>
<div className='hidden md:flex flex-1'></div>
<div className='w-full md:w-auto flex justify-center'>
<div
id='btn-container'
className={cn(
'flex flex-nowrap border border-white rounded-full transition-all bg-gradient-to-r h-[42px]',
'md:text-base sm:text-sm text-xs',
display == 'open' && 'from-red-500 to-40%',
display == 'progress' &&
'via-red-500 from-transparent to-transparent from-[23.33%] to-[76.66%]',
display == 'past' && 'from-transparent from-60% to-red-500',
'gap-2 md:gap-4'
)}
>
past bounties
</button>
<button
onClick={() => setDisplay('open')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 h-full flex items-center justify-center'
>
new bounties
</button>
<button
onClick={() => setDisplay('progress')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 h-full flex items-center justify-center'
>
voting in progress
</button>
<button
onClick={() => setDisplay('past')}
className='flex-grow sm:flex-grow-0 md:px-5 px-3 h-full flex items-center justify-center'
>
past bounties
</button>
</div>
</div>
<div className='w-full md:w-auto flex justify-center md:justify-end mt-2 md:mt-0 md:flex-1 ml-3'>
<FormControl className='h-[36px] md:h-[42px]'>
<Select
id='sort-select'
value={sortType}
className='h-full py-0 bg-[#D1ECFF]/20 text-bold bg-gradient-to-t from-white-200 from-10% via-30% to-50% rounded-full hover:border-white'
sx={{
color: 'white',
'& .MuiSvgIcon-root': { color: 'white' },
'& fieldset': {
borderColor: 'white',
'&:hover': {
borderColor: 'white !important',
},
},
'& .MuiSelect-select': {
padding: '0 32px 0 12px !important',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minWidth: '36px',
minHeight: '36px',
'@media (min-width: 768px)': {
minHeight: '42px',
},
},
'&:hover': {
'& fieldset': {
borderColor: 'white !important',
},
},
'&.Mui-focused': {
'& fieldset': {
borderColor: 'white !important',
},
},
}}
renderValue={() => <SortIcon width={18} height={18} />}
onChange={(e) => setSortType(e.target.value as SortType)}
>
<MenuItem value='value' className='color-white'>
by value
</MenuItem>
{/* id == date */}
<MenuItem value='id' className='color-white'>
by date
</MenuItem>
</Select>
</FormControl>
</div>
</div>

Expand Down
Loading
Loading