From 13a848b27ca758c7028af3d03263bf4e6c36d57f Mon Sep 17 00:00:00 2001 From: gnomadic Date: Tue, 22 Oct 2024 16:44:47 -0400 Subject: [PATCH] iterating --- package.json | 2 + pnpm-lock.yaml | 126 ++++++++++++++++++ .../components/ProjectCard.stories.tsx | 100 ++++++++++++++ .../project/components/ProjectCard.tsx | 98 ++++++++++++++ .../project/components/ProjectCardStates.tsx | 50 +++++++ src/features/project/mocks/objects.ts | 99 ++++++++++++++ src/features/project/types/types.ts | 6 +- src/primitives/Avatar.tsx | 4 +- src/tokens/colors.ts | 1 - src/ui-shadcn/skeleton.tsx | 2 +- 10 files changed, 481 insertions(+), 7 deletions(-) create mode 100644 src/features/project/components/ProjectCard.stories.tsx create mode 100644 src/features/project/components/ProjectCard.tsx create mode 100644 src/features/project/components/ProjectCardStates.tsx create mode 100644 src/features/project/mocks/objects.ts diff --git a/package.json b/package.json index 89fabbb1..a8ea22ae 100644 --- a/package.json +++ b/package.json @@ -124,9 +124,11 @@ "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-toggle-group": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.3", + "@tanstack/react-query": "^5.59.15", "cmdk": "1.0.0", "date-fns": "^4.1.0", "embla-carousel-react": "^8.3.0", + "graphql-request": "^7.1.0", "input-otp": "^1.2.4", "next-themes": "^0.3.0", "react-day-picker": "8.10.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bdfe09bd..e67a1bc6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,6 +92,9 @@ importers: '@radix-ui/react-tooltip': specifier: ^1.1.3 version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-query': + specifier: ^5.59.15 + version: 5.59.15(react@18.3.1) cmdk: specifier: 1.0.0 version: 1.0.0(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -101,6 +104,9 @@ importers: embla-carousel-react: specifier: ^8.3.0 version: 8.3.0(react@18.3.1) + graphql-request: + specifier: ^7.1.0 + version: 7.1.0(graphql@16.9.0) input-otp: specifier: ^1.2.4 version: 1.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -840,6 +846,11 @@ packages: '@fontsource/dm-mono@5.1.0': resolution: {integrity: sha512-cfowZUJJDHjgVFOEQmIn2KHtQ8LDXnTGgTTunUImzzg3Xf6V92MlYR/pmkqIt7lXq7lfP/pQZ9ph/9JeLDRsCQ==} + '@graphql-typed-document-node/core@3.2.0': + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1015,6 +1026,12 @@ packages: '@microsoft/tsdoc@0.15.0': resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==} + '@molt/command@0.9.0': + resolution: {integrity: sha512-1JI8dAlpqlZoXyKWVQggX7geFNPxBpocHIXQCsnxDjKy+3WX4SGyZVJXuLlqRRrX7FmQCuuMAfx642ovXmPA9g==} + + '@molt/types@0.2.0': + resolution: {integrity: sha512-p6ChnEZDGjg9PYPec9BK6Yp5/DdSrYQvXTBAtgrnqX6N36cZy37ql1c8Tc5LclfIYBNG7EZp8NBcRTYJwyi84g==} + '@mswjs/interceptors@0.35.9': resolution: {integrity: sha512-SSnyl/4ni/2ViHKkiZb8eajA/eN1DNFaHjhGiLUdZvDz6PKF4COSf/17xqSz64nOo2Ia29SA6B2KNCsyCbVmaQ==} engines: {node: '>=18'} @@ -2252,6 +2269,14 @@ packages: '@swc/types@0.1.13': resolution: {integrity: sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==} + '@tanstack/query-core@5.59.13': + resolution: {integrity: sha512-Oou0bBu/P8+oYjXsJQ11j+gcpLAMpqW42UlokQYEz4dE7+hOtVO9rVuolJKgEccqzvyFzqX4/zZWY+R/v1wVsQ==} + + '@tanstack/react-query@5.59.15': + resolution: {integrity: sha512-QbVlAkTI78wB4Mqgf2RDmgC0AOiJqer2c5k9STOOSXGv1S6ZkY37r/6UpE8DbQ2Du0ohsdoXgFNEyv+4eDoPEw==} + peerDependencies: + react: ^18 || ^19 + '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} @@ -2631,6 +2656,9 @@ packages: ajv@8.13.0: resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + alge@0.8.1: + resolution: {integrity: sha512-kiV9nTt+XIauAXsowVygDxMZLplZxDWt0W8plE/nB32/V2ziM/P/TxDbSVK7FYIUt2Xo16h3/htDh199LNPCKQ==} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -3674,6 +3702,22 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + graphql-request@7.1.0: + resolution: {integrity: sha512-Ouu/lYVFhARS1aXeZoVJWnGT6grFJXTLwXJuK4mUGGRo0EUk1JkyYp43mdGmRgUVezpRm6V5Sq3t8jBDQcajng==} + hasBin: true + peerDependencies: + '@dprint/formatter': ^0.3.0 + '@dprint/typescript': ^0.91.1 + dprint: ^0.46.2 + graphql: 14 - 16 + peerDependenciesMeta: + '@dprint/formatter': + optional: true + '@dprint/typescript': + optional: true + dprint: + optional: true + graphql@16.9.0: resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} @@ -4231,12 +4275,21 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.flattendeep@4.4.0: resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} + lodash.ismatch@4.4.0: + resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -4945,6 +4998,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readline-sync@1.4.10: + resolution: {integrity: sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==} + engines: {node: '>= 0.8.0'} + recast@0.23.9: resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} engines: {node: '>= 4'} @@ -4976,6 +5033,9 @@ packages: resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} engines: {node: '>=4'} + remeda@1.61.0: + resolution: {integrity: sha512-caKfSz9rDeSKBQQnlJnVW3mbVdFgxgGWQKq1XlFokqjf+hQD5gxutLGTTY2A/x24UxVyJe9gH5fAkFI63ULw4A==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5195,6 +5255,10 @@ packages: resolution: {integrity: sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==} engines: {node: '>=12.20'} + string-length@6.0.0: + resolution: {integrity: sha512-1U361pxZHEQ+FeSjzqRpV+cu2vTzYeWeafXFLykiFlv4Vc0n3njgU8HrMbyik5uwm77naWMuVG8fhEF+Ovb1Kg==} + engines: {node: '>=16'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -5357,6 +5421,9 @@ packages: ts-pattern@5.5.0: resolution: {integrity: sha512-jqbIpTsa/KKTJYWgPNsFNbLVpwCgzXfFJ1ukNn4I8hMwyQzHMJnk/BqWzggB0xpkILuKzaO/aMYhS0SkaJyKXg==} + ts-toolbelt@9.6.0: + resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} + tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -6207,6 +6274,10 @@ snapshots: '@fontsource/dm-mono@5.1.0': {} + '@graphql-typed-document-node/core@3.2.0(graphql@16.9.0)': + dependencies: + graphql: 16.9.0 + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -6511,6 +6582,24 @@ snapshots: '@microsoft/tsdoc@0.15.0': {} + '@molt/command@0.9.0': + dependencies: + '@molt/types': 0.2.0 + alge: 0.8.1 + chalk: 5.3.0 + lodash.camelcase: 4.3.0 + lodash.snakecase: 4.1.1 + readline-sync: 1.4.10 + string-length: 6.0.0 + strip-ansi: 7.1.0 + ts-toolbelt: 9.6.0 + type-fest: 4.26.1 + zod: 3.23.8 + + '@molt/types@0.2.0': + dependencies: + ts-toolbelt: 9.6.0 + '@mswjs/interceptors@0.35.9': dependencies: '@open-draft/deferred-promise': 2.2.0 @@ -7879,6 +7968,13 @@ snapshots: dependencies: '@swc/counter': 0.1.3 + '@tanstack/query-core@5.59.13': {} + + '@tanstack/react-query@5.59.15(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.59.13 + react: 18.3.1 + '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.25.7 @@ -8345,6 +8441,13 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 + alge@0.8.1: + dependencies: + lodash.ismatch: 4.4.0 + remeda: 1.61.0 + ts-toolbelt: 9.6.0 + zod: 3.23.8 + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -9439,6 +9542,13 @@ snapshots: graphemer@1.4.0: {} + graphql-request@7.1.0(graphql@16.9.0): + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@molt/command': 0.9.0 + graphql: 16.9.0 + zod: 3.23.8 + graphql@16.9.0: {} has-flag@3.0.0: {} @@ -10205,10 +10315,16 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.camelcase@4.3.0: {} + lodash.flattendeep@4.4.0: {} + lodash.ismatch@4.4.0: {} + lodash.merge@4.6.2: {} + lodash.snakecase@4.1.1: {} + lodash@4.17.21: {} log-update@6.1.0: @@ -10842,6 +10958,8 @@ snapshots: dependencies: picomatch: 2.3.1 + readline-sync@1.4.10: {} + recast@0.23.9: dependencies: ast-types: 0.16.1 @@ -10895,6 +11013,8 @@ snapshots: dependencies: es6-error: 4.1.1 + remeda@1.61.0: {} + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -11132,6 +11252,10 @@ snapshots: char-regex: 2.0.1 strip-ansi: 7.1.0 + string-length@6.0.0: + dependencies: + strip-ansi: 7.1.0 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -11298,6 +11422,8 @@ snapshots: ts-pattern@5.5.0: {} + ts-toolbelt@9.6.0: {} + tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 diff --git a/src/features/project/components/ProjectCard.stories.tsx b/src/features/project/components/ProjectCard.stories.tsx new file mode 100644 index 00000000..2817266a --- /dev/null +++ b/src/features/project/components/ProjectCard.stories.tsx @@ -0,0 +1,100 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { expect, within } from "@storybook/test"; + +import { ProjectCard } from "./ProjectCard"; +import { QueryError, QueryPending, QuerySuccess, singleProject } from "../mocks/objects"; +import { QueryObserverResult, UseQueryResult } from "@tanstack/react-query"; + +const meta: Meta = { + title: "Components/Project/ProjectCard", + component: ProjectCard, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + project: singleProject, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const avatar = await canvas.findByAltText("avatar"); + let src = avatar.getAttribute("src"); + expect(src).toContain(singleProject.metadata.logoImg); + + const banner = await canvas.findByAltText("banner"); + src = banner.getAttribute("src"); + + expect(src).toContain(singleProject.metadata.bannerImg); + }, +}; + +export const Undefined: Story = { + args: { + project: undefined, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const card = canvas.getByRole("presentation"); + expect(card).toBeVisible(); + + const avatarElement = canvas.queryAllByAltText("avatar"); + expect(avatarElement).toHaveLength(0); + + const bannerElement = canvas.queryAllByAltText("banner"); + expect(bannerElement).toHaveLength(0); + }, +}; + +export const SuccessQuery: Story = { + args: { + queryResult: QuerySuccess, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const avatar = await canvas.findByAltText("avatar"); + let src = avatar.getAttribute("src"); + expect(src).toContain(singleProject.metadata.logoImg); + + const banner = await canvas.findByAltText("banner"); + src = banner.getAttribute("src"); + + expect(src).toContain(singleProject.metadata.bannerImg); + }, +}; + +export const PendingQuery: Story = { + args: { + queryResult: QueryPending, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const card = canvas.getByRole("presentation"); + expect(card).toBeVisible(); + + const avatarElement = canvas.queryAllByAltText("avatar"); + expect(avatarElement).toHaveLength(0); + + const bannerElement = canvas.queryAllByAltText("banner"); + expect(bannerElement).toHaveLength(0); + }, +}; + +export const ErroryQuery: Story = { + args: { + queryResult: QueryError, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const avatarElement = canvas.queryByAltText("avatar"); + expect(avatarElement).toBeNull(); + + const bannerElement = canvas.queryByAltText("banner"); + expect(bannerElement).toBeNull(); + }, +}; diff --git a/src/features/project/components/ProjectCard.tsx b/src/features/project/components/ProjectCard.tsx new file mode 100644 index 00000000..1a4e264f --- /dev/null +++ b/src/features/project/components/ProjectCard.tsx @@ -0,0 +1,98 @@ +import React from "react"; +import { Card, CardContent } from "@/ui-shadcn/card"; +import { match, P } from "ts-pattern"; +import { UseQueryResult } from "@tanstack/react-query"; + +import { Project } from "@/features/project/types/types"; +import { BannerImage } from "@/primitives/BannerImage"; +import { Avatar } from "@/primitives/Avatar"; +import { Skeleton } from "@/ui-shadcn/skeleton"; + +interface ProjectCardProps { + project?: Project | undefined; + queryResult?: UseQueryResult | undefined; +} + +interface ErrorCardProps { + error?: Error | null | undefined; +} + +export function ProjectCard({ project, queryResult }: ProjectCardProps) { + return ( + match({ project, queryResult }) + // everything is nullish + .with({ project: P.nullish, queryResult: P.nullish }, () => ) + // Project is explicitly passed in + .with({ project: P.any, queryResult: P.nullish }, () => ) + // TanStack Query result is passed in and it's an error + .with({ project: P.nullish, queryResult: { status: "error" } }, (match) => ( + + )) + // TanStack Query result is passed in and it's pending + .with({ project: P.nullish, queryResult: { status: "pending" } }, () => ) + // TanStack Query result is passed in and it's a success + .with({ project: P.nullish, queryResult: { status: "success" } }, (match) => ( + + )) + .otherwise(() => ) + ); +} + +// export function ProjectCard({ project, queryResult }: ProjectCardProps) { +// return match({ project, queryResult }) +// // everything is nullish +// .with({ project: P.nullish, queryResult: P.nullish }, () => ) +// // Project is explicitly passed in +// .with({ project: P.any, queryResult: P.nullish }, () => ) +// // TanStack Query result is passed in +// .with({ project: P.nullish, queryResult: P.any }, () => { +// match(queryResult) +// //Tanstack Query result is error +// .with({ status: "error" }, (queryResult) => ) +// //Tanstack Query result is pending +// .with({ status: "pending" }, () => ) +// //Tanstack Query result is success +// .with({ status: "success" }, (queryResult) => ) +// }) +// .otherwise(() => ); + +// } + +function LoadingCard() { + return ( + +
+ +
+ + + + +
+ ); +} + +export function DataCard({ project }: ProjectCardProps) { + return ( + +
+ +
+ +
+
+ +

+ {project?.metadata?.title} +

+

+ {project?.metadata?.description} +

+
+
+ ); +} + +export function ErrorCard({ error }: ErrorCardProps) { + return <>; +} diff --git a/src/features/project/components/ProjectCardStates.tsx b/src/features/project/components/ProjectCardStates.tsx new file mode 100644 index 00000000..02df35bd --- /dev/null +++ b/src/features/project/components/ProjectCardStates.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import { Card, CardContent } from "@/ui-shadcn/card"; + +import { Project } from "@/features/project/types/types"; +import { BannerImage } from "@/primitives/BannerImage"; +import { Avatar } from "@/primitives/Avatar"; +import { Skeleton } from "@/ui-shadcn/skeleton"; + +interface ProjectCardProps { + project?: Project | undefined; +} + +export function ProjectCard({ project }: ProjectCardProps) { + return project === undefined ? : ; +} + +function LoadingCard() { + return ( + +
+ +
+ + + + +
+ ); +} + +export function DataCard({ project }: ProjectCardProps) { + return ( + +
+ +
+ +
+
+ +

+ {project?.metadata?.title} +

+

+ {project?.metadata?.description} +

+
+
+ ); +} diff --git a/src/features/project/mocks/objects.ts b/src/features/project/mocks/objects.ts new file mode 100644 index 00000000..867f0a5f --- /dev/null +++ b/src/features/project/mocks/objects.ts @@ -0,0 +1,99 @@ +import { Project } from "../types/types"; +import { UseQueryResult } from "@tanstack/react-query"; + +export const singleProject: Project = { + id: "0x00065ad5b4ac5b42ac82c60ac9e939505f7996e95b6181919a5353fc50e6b664", + metadata: { + title: "Gitcoin Grants Stack", + logoImg: "QmVSEo7Q1NFok7AT3vqD55EoThBgujoF1KXhiph9T9MNTr", + bannerImg: "QmXE6wP4Zsqp6VdNtXjv2EwqJpCTcBZfZNdSKSbjzEKKtn", + description: + "Gitcoin Grants Stack is a protocol-enabled solution that enables any community to easily create, manage and grow a grants program. From deployment and application management, to funds allocation, Grants Stack takes the hassle out of running a grants program.", + projectGithub: "", + projectTwitter: "", + }, +}; + +export const QueryPending: UseQueryResult = { + status: "pending" as const, + data: undefined, + error: null, + isLoading: false, + isFetching: false, + isPending: true, + isSuccess: false, + isError: false, + isLoadingError: false, + isRefetchError: false, + dataUpdatedAt: 0, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isFetched: true, + isRefetching: false, + isStale: false, + isFetchedAfterMount: true, + isInitialLoading: false, + isPaused: false, + isPlaceholderData: false, + fetchStatus: "idle" as const, + refetch: () => Promise.resolve(QueryPending), + promise: Promise.resolve(singleProject), +}; + +export const QueryError: UseQueryResult = { + status: "error" as const, + data: undefined, + error: new Error("uh oh"), + isLoading: false, + isFetching: false, + isPending: false, + isSuccess: false, + isError: true, + isLoadingError: true, + isRefetchError: false, + dataUpdatedAt: 0, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isFetched: true, + isRefetching: false, + isStale: false, + isFetchedAfterMount: true, + isInitialLoading: false, + isPaused: false, + isPlaceholderData: false, + fetchStatus: "idle" as const, + refetch: () => Promise.resolve(QueryPending), + promise: Promise.resolve(singleProject), +}; + +export const QuerySuccess: UseQueryResult = { + status: "success" as const, + data: singleProject, + error: null, + isLoading: false, + isFetching: false, + isPending: false, + isSuccess: true, + isError: false, + isLoadingError: false, + isRefetchError: false, + dataUpdatedAt: 0, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isFetched: true, + isRefetching: false, + isStale: false, + isFetchedAfterMount: true, + isInitialLoading: false, + isPaused: false, + isPlaceholderData: false, + fetchStatus: "idle" as const, + refetch: () => Promise.resolve(QueryPending), + promise: Promise.resolve(singleProject), +}; diff --git a/src/features/project/types/types.ts b/src/features/project/types/types.ts index 1ddcef74..4f31ffa0 100644 --- a/src/features/project/types/types.ts +++ b/src/features/project/types/types.ts @@ -1,11 +1,11 @@ export interface Project { id: string; - name: string; + name?: string; description?: string; avatarUrl?: string; bannerUrl?: string; - anchorAddress: string; - chainId: number; + anchorAddress?: string; + chainId?: number; metadata: ProjectMetadata; } diff --git a/src/primitives/Avatar.tsx b/src/primitives/Avatar.tsx index 0cd8c7e1..a3e77fda 100644 --- a/src/primitives/Avatar.tsx +++ b/src/primitives/Avatar.tsx @@ -51,10 +51,10 @@ export const Avatar = ({ return ( - + {fallback} ); diff --git a/src/tokens/colors.ts b/src/tokens/colors.ts index 2c9de06e..be6f5fad 100644 --- a/src/tokens/colors.ts +++ b/src/tokens/colors.ts @@ -8,5 +8,4 @@ export const colors: Colors = { }, white: "#ffffff", black: "#000000", - muted: { foreground: "#959C9C" }, }; diff --git a/src/ui-shadcn/skeleton.tsx b/src/ui-shadcn/skeleton.tsx index 26cd4b55..e9c9e10b 100644 --- a/src/ui-shadcn/skeleton.tsx +++ b/src/ui-shadcn/skeleton.tsx @@ -6,7 +6,7 @@ function Skeleton({ }: React.HTMLAttributes) { return (
)