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

fix: visual bugs and fixes #609

Merged
merged 17 commits into from
Mar 30, 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
5 changes: 5 additions & 0 deletions .changeset/five-poets-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blockchain-lab-um/dapp": patch
---

Adds reclaim option for campaigns.
2 changes: 1 addition & 1 deletion packages/dapp/src/app/[locale]/(public)/ecosystem/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const projectsDark: ProjectIconProps[] = [

export default function Page() {
return (
<div className="flex flex-col items-center pt-20">
<div className="flex flex-col">
<div>
<h1 className="font-ubuntu dark:text-orange-accent-dark mb-4 text-center text-2xl font-medium text-pink-500">
Applications
Expand Down
6 changes: 4 additions & 2 deletions packages/dapp/src/app/[locale]/(public)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ export default async function PublicLayout({
children: React.ReactNode;
}) {
return (
<div className="flex min-h-screen flex-col px-4 sm:px-12">
<PublicNavbar />
<div className="flex flex-col h-screen px-4 sm:px-12">
<div className="m-0 p-6 sm:px-12">
<PublicNavbar />
</div>
<div className="flex flex-1">
<div className="flex flex-1 items-center justify-center overflow-auto">
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const metadata: Metadata = {

export default function Page() {
return (
<div className="flex flex-1 items-center justify-center">
<div className="flex w-full pt-12 h-auto items-center justify-center">
<div className="dark:bg-navy-blue-800 dark:text-navy-blue-400 w-full rounded-3xl bg-white shadow-lg md:max-w-4xl">
<SettingsCard />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const metadata: Metadata = {

export default function Page() {
return (
<div className="flex h-full flex-1 justify-center">
<div className="flex h-full justify-center w-full">
<CampaignsDisplay />
</div>
);
Expand Down
20 changes: 11 additions & 9 deletions packages/dapp/src/app/[locale]/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AppNavbar from '@/components/AppNavbar';
import { SignInModal } from '@/components/SignInModal';
import ToastWrapper from '@/components/ToastWrapper';
import { Providers } from '@/components/Providers';
import { ScrollShadow } from '@nextui-org/react';

export default async function AppLayout({
children,
Expand All @@ -13,16 +14,17 @@ export default async function AppLayout({
}) {
return (
<Providers>
<AppNavbar />
<div
className={clsx(
'flex min-h-screen flex-col justify-center pt-24',
'main-bg'
)}
>
<div className="flex h-full w-full flex-1 flex-col px-2 pb-20 pt-12 sm:px-6 md:px-12">
{children}
<div className="flex flex-col h-screen px-4 pb-6 sm:px-12">
<div className="p-6 m-0 sm:px-2 max-sm:py-2">
<AppNavbar />
</div>
<ScrollShadow
className="flex h-full w-full flex-col py-6 px-2 main-bg max-sm:mb-12"
hideScrollBar
size={8}
>
{children}
</ScrollShadow>
</div>
<AppBottomBar />
<SignInModal />
Expand Down
58 changes: 58 additions & 0 deletions packages/dapp/src/app/api/campaigns/claims/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { type NextRequest, NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
import { supabaseServiceRoleClient } from '@/utils/supabase/supabaseServiceRoleClient';
import { supabaseClient } from '@/utils/supabase/supabaseClient';

const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};

export const dynamic = 'force-dynamic';

export async function GET(request: NextRequest) {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return new NextResponse('Unauthorized', {
status: 401,
headers: {
...CORS_HEADERS,
},
});
}
const user = jwt.verify(token, process.env.SUPABASE_JWT_SECRET!) as {
sub: string;
address: string;
aud: string;
role: string;
iat: number;
exp: number;
};

const supabase = supabaseServiceRoleClient();
const { data: userId } = await supabase
.from('users')
.select('id')
.eq('address', user.address.toLowerCase())
.single();
if (!userId) {
return NextResponse.json({ claims: [] }, { headers: { ...CORS_HEADERS } });
}
const { data: claims, error } = await supabase
.from('claims')
.select('*')
.eq('user_id', userId.id);

if (error) {
console.error('Error getting claims', error);
return new NextResponse('Error getting claims', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}

return NextResponse.json({ claims }, { headers: { ...CORS_HEADERS } });
}
75 changes: 48 additions & 27 deletions packages/dapp/src/app/api/campaigns/issue/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,54 @@ export async function POST(request: NextRequest) {
},
});
}
const supabase = supabaseServiceRoleClient();
const { data: campaign, error: campaignError } = await supabase
.from('campaigns')
.select('*, requirements(id, *)')
.eq('id', campaignId)
.order('created_at', { ascending: false })
.single()
.throwOnError();

if (campaignError) {
return new NextResponse('Campaign not found', {
status: 404,
headers: {
...CORS_HEADERS,
},
});
}

if (campaign.total && campaign.claimed >= campaign.total) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}
const { data: completedRequirements, error: completedRequirementsError } =
await supabase.rpc('get_num_of_users_requirements_by_campaign', {
campaign_id: campaignId,
user_id: user.sub,
});

if (completedRequirementsError) {
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}
if (completedRequirements !== campaign.requirements.length) {
return new NextResponse('User has not completed all requirements', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}

const agent = await getAgent();
const didResolution = await agent.resolveDid({ didUrl: did });
Expand Down Expand Up @@ -87,33 +135,6 @@ export async function POST(request: NextRequest) {
});
}

const supabase = supabaseServiceRoleClient();

const { data: campaign, error: campaignError } = await supabase
.from('campaigns')
.select('*')
.eq('id', campaignId)
.single()
.throwOnError();

if (campaignError) {
return new NextResponse('Campaign not found', {
status: 404,
headers: {
...CORS_HEADERS,
},
});
}

if (campaign.total && campaign.claimed >= campaign.total) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}

const { data: claim, error: claimError } = await supabase
.from('claims')
.select('*')
Expand Down
6 changes: 3 additions & 3 deletions packages/dapp/src/components/AppNavbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export default function AppNavbar() {
const { isConnected } = useAccount();

return (
<div className="main-bg fixed top-0 z-50 m-0 flex h-24 w-screen items-center">
<div className="flex flex-1 items-center px-4 sm:px-12">
<div className="z-50 items-center">
<div className="flex flex-1 items-center">
<Link href="/" className="focus-visible:outline-none">
<div className="flex">
<MascaLogo />
Expand All @@ -45,7 +45,7 @@ export default function AppNavbar() {
</h1>
</div>
</Link>
<div className="mx-2 hidden flex-1 items-center justify-center md:flex">
<div className="hidden flex-1 items-center justify-center md:flex">
{MAIN_LINKS.map(({ name, href, requiresConnection }) => {
if ((requiresConnection && isConnected) || !requiresConnection) {
return (
Expand Down
10 changes: 0 additions & 10 deletions packages/dapp/src/components/AuthorizationRequest/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,13 @@ const AuthorizationRequestFlow = () => {
}
};

const sendAuthorizationResponse = async () => {
if (!api || !authorizationRequestURI || !parsedAuthorizationRequestURI) {
return;
}

console.log('here');
};

useEffect(() => {
if (!credentials.length) return;
setIsSelectModalOpen(true);
}, [credentials]);

useEffect(() => {
if (!selectedCredentials.length) return;

console.log(selectedCredentials);
// TODO:
// sendAuthorizationResponse().catch((e) => console.log(e));
}, [selectedCredentials]);
Expand Down
32 changes: 28 additions & 4 deletions packages/dapp/src/components/CampaignsDisplay/CampaignDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
useSwitchChain,
} from '@/hooks';
import { useAccount } from 'wagmi';
import { RewardDisplay } from './RewardDisplay';

type CampaignProps = {
campaign: Campaigns[number];
alreadyClaimed: boolean;
};

export const CampaignDisplay = ({
Expand All @@ -28,7 +30,9 @@ export const CampaignDisplay = ({
total,
image_url: imageUrl,
requirements,
rewards,
},
alreadyClaimed,
}: CampaignProps) => {
const t = useTranslations('CampaignDisplay');

Expand Down Expand Up @@ -122,6 +126,12 @@ export const CampaignDisplay = ({
<p className="text-md dark:text-navy-blue-400 mt-4 text-gray-600">
{description}
</p>
<h5 className="font-ubuntu dark:text-navy-blue-200 mt-8 text-lg font-medium leading-6 text-gray-700">
{t('rewards')}
</h5>
<div className="mt-2 w-full">
<RewardDisplay reward={rewards!} />
</div>
{requirements.length > 0 && (
<h5 className="font-ubuntu dark:text-navy-blue-200 mt-8 text-lg font-medium leading-6 text-gray-700">
{t('requirements')}
Expand All @@ -142,13 +152,27 @@ export const CampaignDisplay = ({
<Button
variant="primary"
size="sm"
disabled={!did || isClaiming || claimed === total || !address}
onClick={() =>
isSignedIn ? handleClaim() : changeIsSignInModalOpen(true)
disabled={
!did ||
isClaiming ||
(!alreadyClaimed && claimed === total) ||
!address ||
!requirements.every((reqToCheck) =>
completedRequirements.some(
(completedReq) => completedReq === reqToCheck.id
)
)
}
onClick={() => {
if (isSignedIn) {
handleClaim();
} else {
changeIsSignInModalOpen(true);
}
}}
loading={isClaiming}
>
{t('claim')}
{alreadyClaimed ? t('reclaim') : t('claim')}
</Button>
</div>
</div>
Expand Down
17 changes: 17 additions & 0 deletions packages/dapp/src/components/CampaignsDisplay/RewardDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Chip } from '@nextui-org/react';

type RequirementProps = {
reward: string;
};

export const RewardDisplay = ({ reward }: RequirementProps) => {
return (
<div className="mt-8 flex w-full justify-between">
<Chip>
<h2 className="font-ubuntu dark:text-navy-blue-50 flex items-center gap-x-2 text-lg font-medium leading-6 text-gray-800">
{reward}
</h2>
</Chip>
</div>
);
};
Loading