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

real data (rebased) #18

Merged
merged 12 commits into from
Jan 20, 2024
1,164 changes: 1,164 additions & 0 deletions shop/.graphclient/index.ts

Large diffs are not rendered by default.

724 changes: 724 additions & 0 deletions shop/.graphclient/schema.graphql

Large diffs are not rendered by default.

8,361 changes: 8,361 additions & 0 deletions shop/.graphclient/sources/esprit/introspectionSchema.ts

Large diffs are not rendered by default.

724 changes: 724 additions & 0 deletions shop/.graphclient/sources/esprit/schema.graphql

Large diffs are not rendered by default.

723 changes: 723 additions & 0 deletions shop/.graphclient/sources/esprit/types.ts

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions shop/.graphclientrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
sources:
- name: esprit
handler:
graphql:
endpoint: https://api.studio.thegraph.com/query/55887/esprit/version/latest


documents:
- ./src/queries/get_payments.graphql
20,997 changes: 15,685 additions & 5,312 deletions shop/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions shop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"cmdk": "^0.2.0",
"connectkit": "^1.6.0",
"date-fns": "^3.2.0",
"ethers": "^6.10.0",
"framer-motion": "^10.18.0",
"lucide-react": "^0.309.0",
"next": "14.0.4",
Expand All @@ -42,6 +43,7 @@
"wagmi": "^1.4.13"
},
"devDependencies": {
"@graphprotocol/client-cli": "^3.0.0",
"@types/node": "^20",
"@types/qrcode": "^1.5.5",
"@types/react": "^18",
Expand Down
9 changes: 8 additions & 1 deletion shop/src/app/dashboard/components/cash-out-button.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
'use client'

import { PrimaryButton as Button } from '@/components/ui/button'
import { useDashboardData } from '@/data/useDashboardData'

import {
Drawer,
Expand All @@ -12,6 +15,10 @@ import {
} from '@/components/ui/drawer'

export function CashOutButton() {
const { paymentsReceived, paymentsSent } = useDashboardData()
const totalReceivedAmount = paymentsReceived.reduce((acc, payment) => {
return acc + parseFloat(payment.amount)
}, 0)
return (
<Drawer>
<DrawerTrigger asChild>
Expand All @@ -25,7 +32,7 @@ export function CashOutButton() {
Withdraw Funds
</DrawerTitle>
<DrawerDescription className="text-md text-center">
489.97 GHO
${totalReceivedAmount.toFixed(2)} USD
</DrawerDescription>
</DrawerHeader>
<DrawerFooter className="flex justify-end space-x-4">
Expand Down
96 changes: 32 additions & 64 deletions shop/src/app/dashboard/components/recent-sales.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,42 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { RefundButton } from './refund-button'
import { Payment } from '@/data/useDashboardData'

type RecentSalesProps = {
payments: Payment[]
}

function truncateAddress(address: string, chars = 7): string {
return `${address.substring(0, chars + 2)}...${address.substring(
address.length - 4,
)}`
}

export function RecentSales() {
export function RecentSales({ payments }: RecentSalesProps) {
return (
<div className="space-y-8">
<div className="flex items-center">
<Avatar className="h-9 w-9">
<AvatarImage src="/avatars/01.png" alt="Avatar" />
<AvatarFallback>OM</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">Olivia Martin</p>
<p className="text-sm text-muted-foreground">
olivia.martin@email.com
</p>
</div>
<div className="ml-auto font-medium">+$1,999.00</div>
<RefundButton></RefundButton>
</div>
<div className="flex items-center">
<Avatar className="flex h-9 w-9 items-center justify-center space-y-0 border">
<AvatarImage src="/avatars/02.png" alt="Avatar" />
<AvatarFallback>JL</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">Jackson Lee</p>
<p className="text-sm text-muted-foreground">jackson.lee@email.com</p>
</div>
<div className="ml-auto font-medium">+$39.00</div>
<RefundButton></RefundButton>
</div>
<div className="flex items-center">
<Avatar className="h-9 w-9">
<AvatarImage src="/avatars/03.png" alt="Avatar" />
<AvatarFallback>IN</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">Isabella Nguyen</p>
<p className="text-sm text-muted-foreground">
isabella.nguyen@email.com
</p>
</div>
<div className="ml-auto font-medium">+$299.00</div>
<RefundButton></RefundButton>
</div>
<div className="flex items-center">
<Avatar className="h-9 w-9">
<AvatarImage src="/avatars/04.png" alt="Avatar" />
<AvatarFallback>WK</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">William Kim</p>
<p className="text-sm text-muted-foreground">will@email.com</p>
</div>
<div className="ml-auto font-medium">+$99.00</div>
<RefundButton></RefundButton>
</div>
<div className="flex items-center">
<Avatar className="h-9 w-9">
<AvatarImage src="/avatars/05.png" alt="Avatar" />
<AvatarFallback>SD</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">Sofia Davis</p>
<p className="text-sm text-muted-foreground">sofia.davis@email.com</p>
{payments.map((payment) => (
<div key={payment.id} className="flex items-center">
<Avatar className="h-9 w-9">
<AvatarImage src="/avatars/01.png" alt="Avatar" />
<AvatarFallback>0x</AvatarFallback>
</Avatar>
<div className="ml-4 space-y-1">
<p className="text-sm font-medium leading-none">
{' '}
{truncateAddress(payment.from)}
</p>
<p className="text-sm text-muted-foreground">
{payment.timestamp.toLocaleDateString()}{' '}
</p>
</div>
<div className="ml-auto font-medium">
+${parseFloat(payment.amount).toFixed(2)}
</div>

<RefundButton />
</div>
<div className="ml-auto font-medium">+$39.00</div>
<RefundButton></RefundButton>
</div>
))}
</div>
)
}
8 changes: 4 additions & 4 deletions shop/src/app/dashboard/components/team-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ const groups = [
label: 'Teams',
teams: [
{
label: 'Nice Shoes Inc.',
value: 'nice-shoes-inc',
label: 'Nike EU',
value: 'nike-eu',
},
{
label: 'Cool Poaps Inc.',
value: 'cool-poaps-inc',
label: 'Nike USA',
value: 'nike-usa',
},
],
},
Expand Down
2 changes: 1 addition & 1 deletion shop/src/app/dashboard/components/user-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function UserNav() {
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">stani</p>
<p className="text-xs leading-none text-muted-foreground">
gm@aave.com
gm@nike.com
</p>
</div>
</DropdownMenuLabel>
Expand Down
49 changes: 19 additions & 30 deletions shop/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Metadata } from 'next'
import Image from 'next/image'
import { PrimaryButton as Button } from '@/components/ui/button'
'use client'

import {
Card,
CardContent,
Expand All @@ -10,39 +9,23 @@ import {
CardTitle,
} from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { CalendarDateRangePicker } from '@/app/dashboard/components/date-range-picker'
import { MainNav } from '@/app/dashboard/components/main-nav'
import { Overview } from '@/app/dashboard/components/overview'
import { RecentSales } from '@/app/dashboard/components/recent-sales'
import { Search } from '@/app/dashboard/components/search'
import TeamSwitcher from '@/app/dashboard/components/team-switcher'
import { UserNav } from '@/app/dashboard/components/user-nav'
import { CashOutButton } from './components/cash-out-button'

export const metadata: Metadata = {
title: 'Dashboard',
description: 'Merchant Dashboard for Esprit Payments App',
}
import { Payment, useDashboardData } from '@/data/useDashboardData'

export default function DashboardPage() {
const { paymentsReceived, paymentsSent } = useDashboardData()
const numberOfPaymentsReceived = paymentsReceived.length
const totalReceivedAmount = paymentsReceived.reduce((acc, payment) => {
return acc + parseFloat(payment.amount)
}, 0)
return (
<>
<div className="md:hidden">
<Image
src="/examples/dashboard-light.png"
width={1280}
height={866}
alt="Dashboard"
className="block dark:hidden"
/>
<Image
src="/examples/dashboard-dark.png"
width={1280}
height={866}
alt="Dashboard"
className="hidden dark:block"
/>
</div>
<div className="hidden flex-col md:flex">
<div className="border-b">
<div className="flex h-16 items-center px-4">
Expand Down Expand Up @@ -97,7 +80,9 @@ export default function DashboardPage() {
</svg>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">$45,231.89</div>
<div className="text-2xl font-bold">
${totalReceivedAmount.toFixed(2)}
</div>
<p className="text-xs text-muted-foreground">
+20.1% from last month
</p>
Expand All @@ -106,7 +91,7 @@ export default function DashboardPage() {
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Subscriptions
Total Customers
</CardTitle>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -132,7 +117,9 @@ export default function DashboardPage() {
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Sales</CardTitle>
<CardTitle className="text-sm font-medium">
Recent Sales
</CardTitle>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
Expand All @@ -148,7 +135,9 @@ export default function DashboardPage() {
</svg>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">+12,234</div>
<div className="text-2xl font-bold">
+{numberOfPaymentsReceived}
</div>
<p className="text-xs text-muted-foreground">
+19% from last month
</p>
Expand Down Expand Up @@ -197,7 +186,7 @@ export default function DashboardPage() {
</CardDescription>
</CardHeader>
<CardContent>
<RecentSales />
<RecentSales payments={paymentsReceived} />
</CardContent>
</Card>
</div>
Expand Down
28 changes: 28 additions & 0 deletions shop/src/app/dashboard/test/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use client'

import React from 'react'
import { useDashboardData } from '@/data/useDashboardData'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'

const Page = () => {
const { paymentsReceived, paymentsSent } = useDashboardData()

const totalReceivedAmount = paymentsReceived.reduce((acc, payment) => {
return acc + parseFloat(payment.amount)
}, 0)

return (
<Card>
<CardHeader>
<CardTitle>Payments Received</CardTitle>
</CardHeader>
<CardContent>
{/* Display the payments data */}
<pre>{JSON.stringify(paymentsReceived, null, 2)}</pre>
<div>Total Received ${totalReceivedAmount.toFixed(2)} USD</div>
</CardContent>
</Card>
)
}

export default Page
52 changes: 52 additions & 0 deletions shop/src/data/useDashboardData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useEffect, useState } from 'react';
import { PaymentsReceivedDocument, PaymentsSentDocument, execute } from '../../.graphclient';
import { ethers } from 'ethers';

export type Payment = {
direction: 'sent' | 'received';
amount: string;
transactionHash: string;
timestamp: Date;
id: string;
from: string;
to: string;
};

const MERCHANT_ADDRESS = '0xa79b0396ad597ef7328a97887eD0A955967be2C9';

export const useDashboardData = () => {
const [paymentsReceived, setPaymentsReceived] = useState<Payment[]>([]);
const [paymentsSent, setPaymentsSent] = useState<Payment[]>([]);

useEffect(() => {
const fetchData = async () => {
// Fetch payments received
const received = await execute(PaymentsReceivedDocument, { user: MERCHANT_ADDRESS });
const formattedReceived = received.data.payments.map((payment: any) => ({
direction: 'received',
amount: ethers.formatUnits(payment.amount, 18),
timestamp: new Date(parseInt(payment.blockTimestamp) * 1000),
transactionHash: payment.transactionHash,
id: payment.id,
from: payment.from,
}));
setPaymentsReceived(formattedReceived);

// Fetch payments sent
const sent = await execute(PaymentsSentDocument, { user: MERCHANT_ADDRESS });
const formattedSent = sent.data.payments.map((payment: any) => ({
direction: 'sent',
amount: ethers.formatUnits(payment.amount, 18),
timestamp: new Date(parseInt(payment.blockTimestamp) * 1000),
transactionHash: payment.transactionHash,
id: payment.id,
to: payment.to,
}));
setPaymentsSent(formattedSent);
};

fetchData();
}, []);

return { paymentsReceived, paymentsSent };
};
Loading