mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-27 03:04:24 +01:00
feat: connect donation sats api, build donation sat skeleton, build donation sats mock api
This commit is contained in:
@@ -85,10 +85,10 @@ export interface NexusGenObjects {
|
||||
payment_request: string; // String!
|
||||
}
|
||||
DonationsStats: { // root type
|
||||
applications: number; // Int!
|
||||
donations: number; // Int!
|
||||
prizes: number; // Int!
|
||||
touranments: number; // Int!
|
||||
applications: string; // String!
|
||||
donations: string; // String!
|
||||
prizes: string; // String!
|
||||
touranments: string; // String!
|
||||
}
|
||||
Hackathon: { // root type
|
||||
cover_image: string; // String!
|
||||
@@ -232,10 +232,10 @@ export interface NexusGenFieldTypes {
|
||||
payment_request: string; // String!
|
||||
}
|
||||
DonationsStats: { // field return type
|
||||
applications: number; // Int!
|
||||
donations: number; // Int!
|
||||
prizes: number; // Int!
|
||||
touranments: number; // Int!
|
||||
applications: string; // String!
|
||||
donations: string; // String!
|
||||
prizes: string; // String!
|
||||
touranments: string; // String!
|
||||
}
|
||||
Hackathon: { // field return type
|
||||
cover_image: string; // String!
|
||||
@@ -289,7 +289,7 @@ export interface NexusGenFieldTypes {
|
||||
allTopics: NexusGenRootTypes['Topic'][]; // [Topic!]!
|
||||
getAllHackathons: NexusGenRootTypes['Hackathon'][]; // [Hackathon!]!
|
||||
getCategory: NexusGenRootTypes['Category']; // Category!
|
||||
getDonationsStats: NexusGenRootTypes['DonationsStats'][]; // [DonationsStats!]!
|
||||
getDonationsStats: NexusGenRootTypes['DonationsStats']; // DonationsStats!
|
||||
getFeed: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails!
|
||||
getPostById: NexusGenRootTypes['Post']; // Post!
|
||||
@@ -411,10 +411,10 @@ export interface NexusGenFieldTypeNames {
|
||||
payment_request: 'String'
|
||||
}
|
||||
DonationsStats: { // field return type name
|
||||
applications: 'Int'
|
||||
donations: 'Int'
|
||||
prizes: 'Int'
|
||||
touranments: 'Int'
|
||||
applications: 'String'
|
||||
donations: 'String'
|
||||
prizes: 'String'
|
||||
touranments: 'String'
|
||||
}
|
||||
Hackathon: { // field return type name
|
||||
cover_image: 'String'
|
||||
|
||||
@@ -58,10 +58,10 @@ type Donation {
|
||||
}
|
||||
|
||||
type DonationsStats {
|
||||
applications: Int!
|
||||
donations: Int!
|
||||
prizes: Int!
|
||||
touranments: Int!
|
||||
applications: String!
|
||||
donations: String!
|
||||
prizes: String!
|
||||
touranments: String!
|
||||
}
|
||||
|
||||
type Hackathon {
|
||||
@@ -138,7 +138,7 @@ type Query {
|
||||
allTopics: [Topic!]!
|
||||
getAllHackathons(sortBy: String, topic: Int): [Hackathon!]!
|
||||
getCategory(id: Int!): Category!
|
||||
getDonationsStats: [DonationsStats!]!
|
||||
getDonationsStats: DonationsStats!
|
||||
getFeed(skip: Int = 0, sortBy: String = "all", take: Int = 10, topic: Int = 0): [Post!]!
|
||||
getLnurlDetailsForProject(project_id: Int!): LnurlDetails!
|
||||
getPostById(id: Int!, type: POST_TYPE!): Post!
|
||||
|
||||
@@ -106,31 +106,36 @@ const confirmDonateMutation = extendType({
|
||||
const DonationsStats = objectType({
|
||||
name: 'DonationsStats',
|
||||
definition(t) {
|
||||
t.nonNull.int("prizes");
|
||||
t.nonNull.int("touranments");
|
||||
t.nonNull.int("donations");
|
||||
t.nonNull.int("applications");
|
||||
t.nonNull.string("prizes");
|
||||
t.nonNull.string("touranments");
|
||||
t.nonNull.string("donations");
|
||||
t.nonNull.string("applications");
|
||||
},
|
||||
})
|
||||
|
||||
const getDonationsStats = extendType({
|
||||
type: "Query",
|
||||
definition(t) {
|
||||
t.nonNull.list.nonNull.field('getDonationsStats', {
|
||||
t.nonNull.field('getDonationsStats', {
|
||||
type: "DonationsStats",
|
||||
resolve() {
|
||||
return {
|
||||
prizes: 2600,
|
||||
touranments: 2,
|
||||
donations: prisma.donation.aggregate({
|
||||
async resolve() {
|
||||
const [donations, applications] = await Promise.all([
|
||||
prisma.donation.aggregate({
|
||||
_sum: {
|
||||
amount: true
|
||||
},
|
||||
where: {
|
||||
paid: true
|
||||
}
|
||||
}),
|
||||
applications: prisma.project.count()
|
||||
}).then(d => d._sum.amount),
|
||||
prisma.project.count()]);
|
||||
|
||||
// #TODO add a measurement unit for prizes & donations (eg. $ or sats or BTC)
|
||||
return {
|
||||
prizes: 2600,
|
||||
touranments: 2,
|
||||
donations,
|
||||
applications
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function DonateCard() {
|
||||
<form onSubmit={requestPayment} className="mt-32 ">
|
||||
<div className="input-wrapper">
|
||||
<input
|
||||
className={` input-text input-removed-arrows`}
|
||||
className={`input-text input-removed-arrows`}
|
||||
value={donationAmount} onChange={onChangeInput}
|
||||
type="number"
|
||||
placeholder="1,000"
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function DonatePage() {
|
||||
items={[
|
||||
{
|
||||
heading: "How are donations spent?",
|
||||
content: <p className="whitespace-pre-line">
|
||||
content: <p className=" whitespace-pre-line">
|
||||
Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there.
|
||||
<br />
|
||||
Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.
|
||||
@@ -26,7 +26,7 @@ export default function DonatePage() {
|
||||
},
|
||||
{
|
||||
heading: "Who is working on BOLT🔩FUN?",
|
||||
content: <p className="whitespace-pre-line">
|
||||
content: <p className=" whitespace-pre-line">
|
||||
Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there.
|
||||
<br />
|
||||
Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.
|
||||
@@ -34,7 +34,7 @@ export default function DonatePage() {
|
||||
},
|
||||
{
|
||||
heading: "How can makers win prizes?",
|
||||
content: <p className="whitespace-pre-line">
|
||||
content: <p className=" whitespace-pre-line">
|
||||
Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there.
|
||||
<br />
|
||||
Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.
|
||||
@@ -42,7 +42,7 @@ export default function DonatePage() {
|
||||
},
|
||||
{
|
||||
heading: "How can I donate?",
|
||||
content: <p className="whitespace-pre-line">
|
||||
content: <p className=" whitespace-pre-line">
|
||||
Shock the Web is a virtual hackathon to promote, explore, build and design web applications that can interact with WebLN enabled wallets and browsers. We want to make building on bitcoin more accessible to the masses of web developers out there.
|
||||
<br />
|
||||
Bitcoin development can seem scary for new developers coming in, but it doesn't have to be. With the lightning network's toolkit and libraries a bunch of new opportunities are waiting to be explored. We hope these hackathons can be a chance for you to preview what is possible on bitcoin and the lightning network by fostering collaboration, hopefully shortening (or easing) any developer onboarding time, and helping you connect with other bitcoiners in a fun and friendly space.
|
||||
|
||||
@@ -1,32 +1,47 @@
|
||||
import { BiCoinStack } from "react-icons/bi";
|
||||
import { FiGrid } from "react-icons/fi";
|
||||
import { IoMedalOutline, IoRocketOutline } from "react-icons/io5";
|
||||
import { useDonationsStatsQuery } from "src/graphql";
|
||||
import { generateList } from "src/utils/helperFunctions";
|
||||
import StatCard from "../StatCard/StatCard";
|
||||
import StatCardSkeleton from "../StatCard/StatCard.Skeleton";
|
||||
|
||||
|
||||
export default function DonationStats() {
|
||||
|
||||
const donationsStatQuery = useDonationsStatsQuery();
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="grid sm:grid-cols-2 md:grid-cols-4 gap-16">
|
||||
<StatCard
|
||||
color="#8B5CF6"
|
||||
label={<><BiCoinStack className='scale-125 mr-8' /> <span className="align-middle">Donations</span></>}
|
||||
value='$2.6k'
|
||||
/>
|
||||
<StatCard
|
||||
color="#F59E0B"
|
||||
label={<><IoRocketOutline className='scale-125 mr-8' /> <span className="align-middle">Tournaments</span></>}
|
||||
value='1'
|
||||
/>
|
||||
<StatCard
|
||||
color="#22C55E"
|
||||
label={<><IoMedalOutline className='scale-125 mr-8' /> <span className="align-middle">Prizes</span></>}
|
||||
value='$2.5k'
|
||||
/>
|
||||
<StatCard
|
||||
color="#3B82F6"
|
||||
label={<><FiGrid className='scale-125 mr-8' /> <span className="align-middle">Applications</span></>}
|
||||
value='36'
|
||||
/>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-16">
|
||||
|
||||
{donationsStatQuery.loading && generateList(<StatCardSkeleton />, 4)}
|
||||
|
||||
{!donationsStatQuery.loading &&
|
||||
<>
|
||||
<StatCard
|
||||
color="#8B5CF6"
|
||||
label={<><BiCoinStack className='w-full lg:w-auto scale-125 mr-8' /> <span className="align-middle">Donations</span></>}
|
||||
value={donationsStatQuery.data?.getDonationsStats.donations}
|
||||
/>
|
||||
<StatCard
|
||||
color="#F59E0B"
|
||||
label={<><IoRocketOutline className='w-full lg:w-auto scale-125 mr-8' /> <span className="align-middle">Tournaments</span></>}
|
||||
value={donationsStatQuery.data?.getDonationsStats.touranments}
|
||||
/>
|
||||
<StatCard
|
||||
color="#22C55E"
|
||||
label={<><IoMedalOutline className='w-full lg:w-auto scale-125 mr-8' /> <span className="align-middle">Prizes</span></>}
|
||||
value={donationsStatQuery.data?.getDonationsStats.prizes}
|
||||
/>
|
||||
<StatCard
|
||||
color="#3B82F6"
|
||||
label={<><FiGrid className='w-full lg:w-auto scale-125 mr-8' /> <span className="align-middle">Applications</span></>}
|
||||
value={donationsStatQuery.data?.getDonationsStats.applications}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
query DonationsStats {
|
||||
getDonationsStats {
|
||||
prizes
|
||||
touranments
|
||||
donations
|
||||
applications
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import styles from './styles.module.scss'
|
||||
export default function Header() {
|
||||
return (
|
||||
<div className={`${styles.header}`}>
|
||||
<div>
|
||||
<div className='min-w-0'>
|
||||
<div className="flex items-center gap-24 flex-col md:flex-row">
|
||||
<div>
|
||||
<h1 className="text-[54px] font-bolder">
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
padding: 56px 0;
|
||||
min-height: calc(min(1080px, 90vh));
|
||||
background: #ffecf9;
|
||||
background: linear-gradient(40deg, white -5%, #ffb7d963 74%, #e3faff61 100%);
|
||||
background: linear-gradient(40deg, white 7%, #ffdadaa3 62%, #d0f6ff5c 96%);
|
||||
background-size: 120% 120%;
|
||||
|
||||
animation: Animation 3s ease infinite;
|
||||
display: grid;
|
||||
grid-template-areas: ". content .";
|
||||
grid-template-columns: minmax(16px, 1fr) minmax(auto, 910px) minmax(16px, 1fr);
|
||||
@@ -14,3 +16,15 @@
|
||||
grid-area: content;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Animation {
|
||||
0% {
|
||||
background-position: 0% 20%;
|
||||
}
|
||||
50% {
|
||||
background-position: 20% 0%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import Skeleton from 'react-loading-skeleton'
|
||||
|
||||
|
||||
export default function StatCardSkeleton() {
|
||||
return (
|
||||
<div className="bg-white p-24 rounded-16 text-center" >
|
||||
<p className="text-body4">
|
||||
<Skeleton width={'10ch'} />
|
||||
</p>
|
||||
<p className="text-h2 mt-8">
|
||||
<Skeleton width={'4ch'} />
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
import { FiGrid } from 'react-icons/fi'
|
||||
import StatCard from './StatCard';
|
||||
import StatCardSkeleton from './StatCard.Skeleton';
|
||||
|
||||
export default {
|
||||
title: 'Donations/Donate Page/StatCard',
|
||||
@@ -20,4 +21,9 @@ Default.args = {
|
||||
value: '36'
|
||||
}
|
||||
|
||||
const LoadingTemplate: ComponentStory<typeof StatCard> = (args) => <div className="max-w-[220px]"><StatCardSkeleton ></StatCardSkeleton></div>
|
||||
|
||||
export const Loading = LoadingTemplate.bind({});
|
||||
Loading.args = {
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function StatCard(props: Props) {
|
||||
<p className="text-body4">
|
||||
{props.label}
|
||||
</p>
|
||||
<p className="text-h2 mt-8 font-bolder">
|
||||
<p className="text-h3 sm:text-h2 mt-8 font-bolder">
|
||||
{props.value}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -76,10 +76,10 @@ export type Donation = {
|
||||
|
||||
export type DonationsStats = {
|
||||
__typename?: 'DonationsStats';
|
||||
applications: Scalars['Int'];
|
||||
donations: Scalars['Int'];
|
||||
prizes: Scalars['Int'];
|
||||
touranments: Scalars['Int'];
|
||||
applications: Scalars['String'];
|
||||
donations: Scalars['String'];
|
||||
prizes: Scalars['String'];
|
||||
touranments: Scalars['String'];
|
||||
};
|
||||
|
||||
export type Hackathon = {
|
||||
@@ -186,7 +186,7 @@ export type Query = {
|
||||
allTopics: Array<Topic>;
|
||||
getAllHackathons: Array<Hackathon>;
|
||||
getCategory: Category;
|
||||
getDonationsStats: Array<DonationsStats>;
|
||||
getDonationsStats: DonationsStats;
|
||||
getFeed: Array<Post>;
|
||||
getLnurlDetailsForProject: LnurlDetails;
|
||||
getPostById: Post;
|
||||
@@ -350,6 +350,11 @@ export type SearchProjectsQueryVariables = Exact<{
|
||||
|
||||
export type SearchProjectsQuery = { __typename?: 'Query', searchProjects: Array<{ __typename?: 'Project', id: number, thumbnail_image: string, title: string, category: { __typename?: 'Category', title: string, id: number } }> };
|
||||
|
||||
export type DonationsStatsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type DonationsStatsQuery = { __typename?: 'Query', getDonationsStats: { __typename?: 'DonationsStats', prizes: string, touranments: string, donations: string, applications: string } };
|
||||
|
||||
export type DonateMutationVariables = Exact<{
|
||||
amountInSat: Scalars['Int'];
|
||||
}>;
|
||||
@@ -531,6 +536,43 @@ export function useSearchProjectsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt
|
||||
export type SearchProjectsQueryHookResult = ReturnType<typeof useSearchProjectsQuery>;
|
||||
export type SearchProjectsLazyQueryHookResult = ReturnType<typeof useSearchProjectsLazyQuery>;
|
||||
export type SearchProjectsQueryResult = Apollo.QueryResult<SearchProjectsQuery, SearchProjectsQueryVariables>;
|
||||
export const DonationsStatsDocument = gql`
|
||||
query DonationsStats {
|
||||
getDonationsStats {
|
||||
prizes
|
||||
touranments
|
||||
donations
|
||||
applications
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useDonationsStatsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useDonationsStatsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useDonationsStatsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useDonationsStatsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useDonationsStatsQuery(baseOptions?: Apollo.QueryHookOptions<DonationsStatsQuery, DonationsStatsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<DonationsStatsQuery, DonationsStatsQueryVariables>(DonationsStatsDocument, options);
|
||||
}
|
||||
export function useDonationsStatsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DonationsStatsQuery, DonationsStatsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<DonationsStatsQuery, DonationsStatsQueryVariables>(DonationsStatsDocument, options);
|
||||
}
|
||||
export type DonationsStatsQueryHookResult = ReturnType<typeof useDonationsStatsQuery>;
|
||||
export type DonationsStatsLazyQueryHookResult = ReturnType<typeof useDonationsStatsLazyQuery>;
|
||||
export type DonationsStatsQueryResult = Apollo.QueryResult<DonationsStatsQuery, DonationsStatsQueryVariables>;
|
||||
export const DonateDocument = gql`
|
||||
mutation Donate($amountInSat: Int!) {
|
||||
donate(amount_in_sat: $amountInSat) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
GetHackathonsQueryVariables,
|
||||
AllTopicsQuery,
|
||||
AllTopicsQueryVariables,
|
||||
DonationsStatsQuery,
|
||||
} from 'src/graphql'
|
||||
|
||||
const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000))
|
||||
@@ -172,4 +173,20 @@ export const handlers = [
|
||||
)
|
||||
}),
|
||||
|
||||
|
||||
graphql.query<DonationsStatsQuery>('DonationsStats', async (req, res, ctx) => {
|
||||
await delay()
|
||||
|
||||
return res(
|
||||
ctx.data({
|
||||
getDonationsStats: {
|
||||
applications: '32',
|
||||
donations: "$2.6k",
|
||||
prizes: "$2.5k",
|
||||
touranments: "1",
|
||||
}
|
||||
})
|
||||
)
|
||||
}),
|
||||
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { ComponentProps, ComponentType, Suspense } from "react";
|
||||
import React, { ComponentProps, ComponentType, ReactNode, Suspense } from "react";
|
||||
import { RotatingLines } from "react-loader-spinner";
|
||||
|
||||
export function random(min: number, max: number) {
|
||||
@@ -85,3 +85,8 @@ export function shuffle<T>(_array: Array<T>) {
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
export function generateList(component: React.ReactElement, cnt: number) {
|
||||
return Array(cnt).fill(0).map((_, idx) => React.cloneElement(component, { key: idx }))
|
||||
}
|
||||
Reference in New Issue
Block a user