diff --git a/frontend/.astro/data-store.json b/frontend/.astro/data-store.json index 0b2f8b0..b6340ec 100644 --- a/frontend/.astro/data-store.json +++ b/frontend/.astro/data-store.json @@ -1 +1 @@ -[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.13.7","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/node\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/Users/theodoreabitbol/Desktop/TheGuildGenesis/frontend/node_modules/.astro/sessions\"}}}"] \ No newline at end of file +[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.14.1","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/node\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/home/phoebe/TheGuildGenesis/frontend/node_modules/.astro/sessions\"}}}"] \ No newline at end of file diff --git a/frontend/.astro/settings.json b/frontend/.astro/settings.json index 6e73642..cf5b02c 100644 --- a/frontend/.astro/settings.json +++ b/frontend/.astro/settings.json @@ -1,6 +1,6 @@ { "_variables": { - "lastUpdateCheck": 1758201525305 + "lastUpdateCheck": 1759589860759 }, "eslint.validate": [ "javascript", diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b8a0f1c..386164f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,7 +25,7 @@ "@tanstack/react-router": "^1.131.36", "@types/react": "^19.1.12", "@types/react-dom": "^19.1.9", - "astro": "^5.13.7", + "astro": "^5.14.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.2.2", @@ -97,17 +97,17 @@ "license": "MIT" }, "node_modules/@astrojs/markdown-remark": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.6.tgz", - "integrity": "sha512-bwylYktCTsLMVoCOEHbn2GSUA3c5KT/qilekBKA3CBng0bo1TYjNZPr761vxumRk9kJGqTOtU+fgCAp5Vwokug==", + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.7.tgz", + "integrity": "sha512-KXGdq6/BC18doBCYXp08alHlWChH0hdD2B1qv9wIyOHbvwI5K6I7FhSta8dq1hBQNdun8YkKPR013D/Hm8xd0g==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.7.2", + "@astrojs/internal-helpers": "0.7.3", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", - "import-meta-resolve": "^4.1.0", + "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", @@ -116,8 +116,8 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", - "shiki": "^3.2.1", - "smol-toml": "^1.3.4", + "shiki": "^3.12.2", + "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", @@ -125,6 +125,12 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/markdown-remark/node_modules/@astrojs/internal-helpers": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.3.tgz", + "integrity": "sha512-6Pl0bQEIChuW5wqN7jdKrzWfCscW2rG/Cz+fzt4PhSQX2ivBpnhXgFUCs0M3DCYvjYHnPVG2W36X5rmFjZ62sw==", + "license": "MIT" + }, "node_modules/@astrojs/node": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.4.3.tgz", @@ -5859,60 +5865,60 @@ "license": "0BSD" }, "node_modules/@shikijs/core": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.12.2.tgz", - "integrity": "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz", + "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2", + "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.12.2.tgz", - "integrity": "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz", + "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2", + "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz", - "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz", + "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2", + "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz", - "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz", + "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2" + "@shikijs/types": "3.13.0" } }, "node_modules/@shikijs/themes": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz", - "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz", + "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2" + "@shikijs/types": "3.13.0" } }, "node_modules/@shikijs/types": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz", - "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz", + "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -7993,14 +7999,14 @@ } }, "node_modules/astro": { - "version": "5.13.7", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.13.7.tgz", - "integrity": "sha512-Of2tST7ErbE4y1dVb4aWDXaQSIRBAfraJ4jDqaA3PzPRJOn6Ina36+tQ+8BezjYqiWwRRJdOEE07PRAJXnsddw==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.14.1.tgz", + "integrity": "sha512-gPa8NY7/lP8j8g81iy8UwANF3+aukKRWS68IlthZQNgykpg80ne6lbHOp6FErYycxQ1TUhgEfkXVDQZAoJx8Bg==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.12.2", - "@astrojs/internal-helpers": "0.7.2", - "@astrojs/markdown-remark": "6.3.6", + "@astrojs/internal-helpers": "0.7.3", + "@astrojs/markdown-remark": "6.3.7", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", @@ -8016,7 +8022,7 @@ "cssesc": "^3.0.0", "debug": "^4.4.1", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.1.1", + "devalue": "^5.3.2", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", @@ -8117,6 +8123,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/astro/node_modules/@astrojs/internal-helpers": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.3.tgz", + "integrity": "sha512-6Pl0bQEIChuW5wqN7jdKrzWfCscW2rG/Cz+fzt4PhSQX2ivBpnhXgFUCs0M3DCYvjYHnPVG2W36X5rmFjZ62sw==", + "license": "MIT" + }, "node_modules/astro/node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -16281,17 +16293,17 @@ } }, "node_modules/shiki": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.12.2.tgz", - "integrity": "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz", + "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.12.2", - "@shikijs/engine-javascript": "3.12.2", - "@shikijs/engine-oniguruma": "3.12.2", - "@shikijs/langs": "3.12.2", - "@shikijs/themes": "3.12.2", - "@shikijs/types": "3.12.2", + "@shikijs/core": "3.13.0", + "@shikijs/engine-javascript": "3.13.0", + "@shikijs/engine-oniguruma": "3.13.0", + "@shikijs/langs": "3.13.0", + "@shikijs/themes": "3.13.0", + "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } diff --git a/frontend/package.json b/frontend/package.json index db57557..7b20f8d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -32,7 +32,7 @@ "@tanstack/react-router": "^1.131.36", "@types/react": "^19.1.12", "@types/react-dom": "^19.1.9", - "astro": "^5.13.7", + "astro": "^5.14.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.2.2", diff --git a/frontend/src/components/pages/ProfilePage.tsx b/frontend/src/components/pages/ProfilePage.tsx index 0074f6d..bf61232 100644 --- a/frontend/src/components/pages/ProfilePage.tsx +++ b/frontend/src/components/pages/ProfilePage.tsx @@ -2,6 +2,7 @@ import { AppWrapper } from "@/components/AppWrapper"; import ProfileHeader from "@/components/profiles/profile-page/ProfileHeader"; import ProfileActions from "@/components/profiles/profile-page/ProfileActions"; import ProfileAttestations from "@/components/profiles/profile-page/ProfileAttestations"; +import ProfileIssuedAttestations from "../profiles/profile-page/ProfileIssuedAttestations"; type Props = { address?: string }; @@ -14,6 +15,8 @@ export default function ProfilePage({ address }: Props) { + + ); diff --git a/frontend/src/components/profiles/profile-page/ProfileIssuedAttestations.tsx b/frontend/src/components/profiles/profile-page/ProfileIssuedAttestations.tsx new file mode 100644 index 0000000..db5110f --- /dev/null +++ b/frontend/src/components/profiles/profile-page/ProfileIssuedAttestations.tsx @@ -0,0 +1,116 @@ +import { Send, Badge } from "lucide-react"; +import { useGetAttestations } from "@/hooks/attestations/use-get-attestations"; +import { useMemo } from "react"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { useGetProfiles } from "@/hooks/profiles/use-get-profiles"; + +export function ProfileIssuedAttestations({ address }: { address: string }) { + const attestationsQuery = useGetAttestations(); + const profilesQuery = useGetProfiles(); + + const issuedAttestations = useMemo(() => { + const list = attestationsQuery.data ?? []; + const filtered = list.filter( + (a) => a.issuer.toLowerCase() === (address || "").toLowerCase() + ); + return filtered.map((a, i) => ({ + id: String(i), + badgeName: a.badgeName, + justification: a.attestationJustification, + recipient: a.recipient, + })); + }, [attestationsQuery.data, address]); + + const profileNameByAddress = useMemo(() => { + const map = new Map(); + const list = profilesQuery.data ?? []; + for (const p of list) { + if (p.address) map.set(p.address.toLowerCase(), p.name || ""); + } + return map; + }, [profilesQuery.data]); + + const grouped = useMemo(() => { + const map = new Map< + string, + { id: string; recipient: string; justification: string }[] + >(); + for (const a of issuedAttestations) { + const arr = map.get(a.badgeName) ?? []; + arr.push({ id: a.id, recipient: a.recipient, justification: a.justification }); + map.set(a.badgeName, arr); + } + return Array.from(map.entries()).map(([badgeName, items]) => ({ + badgeName, + items, + })); + }, [issuedAttestations]); + + return ( +
+

+ Issued Attestations ({issuedAttestations.length}) +

+ {issuedAttestations.length === 0 ? ( +

No attestations issued yet.

+ ) : ( + + {grouped.map(({ badgeName, items }, idx) => ( + + +
+ + {" "} + {badgeName || "(unnamed)"} + + + ({items.length}) + +
+
+ + + +
+ ))} +
+ )} +
+ ); +} + +export default ProfileIssuedAttestations; \ No newline at end of file