From fe72b3c0a7c7c80a3bc92bfe49a24af6437053aa Mon Sep 17 00:00:00 2001 From: uche102 Date: Thu, 25 Jun 2026 12:42:33 +0100 Subject: [PATCH 1/2] feat(frontend): add breadcrumb navigation to proposal detail page --- frontend/src/App.tsx | 58 +++++++----- frontend/src/pages/ProposalDetailPage.tsx | 109 ++++++++++++++++++++++ 2 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 frontend/src/pages/ProposalDetailPage.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ed97e16..48f995d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,11 @@ import { useState } from "react"; -import { Link, Route, Routes, useLocation, useNavigate } from "react-router-dom"; +import { + Link, + Route, + Routes, + useLocation, + useNavigate, +} from "react-router-dom"; import { CreateProposalModal } from "./components/CreateProposalModal"; import { useContract } from "./hooks/useContract"; import { useEventPolling } from "./hooks/useEventPolling"; @@ -9,6 +15,7 @@ import { approveProposal, executeProposal, revokeProposal } from "./lib/submit"; import { DashboardPage } from "./pages/DashboardPage"; import { HistoryPage } from "./pages/HistoryPage"; import { OwnersPage } from "./pages/OwnersPage"; +import { ProposalDetailPage } from "./pages/ProposalDetailPage"; import { SettingsPage } from "./pages/SettingsPage"; import { NotFoundPage } from "./pages/NotFoundPage"; @@ -30,27 +37,20 @@ export default function App() { const navigate = useNavigate(); const location = useLocation(); - const { - proposals, - owners, - ownerAddresses, - stats, - loading, - error, - refresh, - } = useContract(wallet.address); + const { proposals, owners, ownerAddresses, stats, loading, error, refresh } = + useContract(wallet.address); useEventPolling(refresh, 5000); useNotifications(wallet.address, proposals); const activeProposals = proposals.filter((proposal) => - ["pending", "ready"].includes(proposal.status) + ["pending", "ready"].includes(proposal.status), ); const isOwner = Boolean( - wallet.address && ownerAddresses.includes(wallet.address) + wallet.address && ownerAddresses.includes(wallet.address), ); const showReadOnlyBanner = Boolean( - wallet.address && !loading && !error && !isOwner + wallet.address && !loading && !error && !isOwner, ); async function withTx(fn: () => Promise) { if (!wallet.address) { @@ -85,7 +85,11 @@ export default function App() { : proposal.status; return withTx(() => approveProposal(wallet.address!, id), { id, - patch: { approvals: newApprovals, status: newStatus, userHasApproved: true }, + patch: { + approvals: newApprovals, + status: newStatus, + userHasApproved: true, + }, }); }; @@ -101,7 +105,7 @@ export default function App() { const thresholdStat = stats.find((stat) => stat.label === "Threshold"); const threshold = Number.parseInt( thresholdStat?.value.split(" ")[0] ?? "0", - 10 + 10, ); function shortenAddr(addr: string) { @@ -112,7 +116,10 @@ export default function App() {
- +
A
@@ -128,7 +135,8 @@ export default function App() { key={label} to={to} className={`rounded-lg px-3 py-1.5 text-sm capitalize transition-colors focus:ring-2 focus:ring-zinc-400 focus:outline-none ${ - location.pathname === to || (to === "/app" && location.pathname === "/app/") + location.pathname === to || + (to === "/app" && location.pathname === "/app/") ? "bg-zinc-800 text-white" : "text-zinc-500 hover:text-zinc-300" }`} @@ -187,7 +195,9 @@ export default function App() { {wallet.networkMismatch && (
- Your wallet network does not match this app. Expected network: {import.meta.env.VITE_NETWORK_PASSPHRASE}. Switch Freighter network to continue. + Your wallet network does not match this app. Expected network:{" "} + {import.meta.env.VITE_NETWORK_PASSPHRASE}. Switch Freighter network + to continue.
)} @@ -222,11 +232,13 @@ export default function App() { />
-

Freighter wallet required

+

+ Freighter wallet required +

Freighter is the supported browser extension for signing Stellar - transactions in Accord. Install it to connect a wallet and use - the app. + transactions in Accord. Install it to connect a wallet and use the + app.

s.label === "Threshold")?.value.split(" ")[0] || "0" + stats.find((s) => s.label === "Threshold")?.value.split(" ")[0] || + "0", )} totalOwners={owners.length} /> @@ -302,6 +315,7 @@ export default function App() { } /> } /> + } /> navigate("/app")} />} diff --git a/frontend/src/pages/ProposalDetailPage.tsx b/frontend/src/pages/ProposalDetailPage.tsx new file mode 100644 index 0000000..4aabca9 --- /dev/null +++ b/frontend/src/pages/ProposalDetailPage.tsx @@ -0,0 +1,109 @@ +import { Link, useParams } from "react-router-dom"; +import { useProposal } from "../hooks/useProposal"; + +export function ProposalDetailPage() { + const { id: idParam } = useParams(); + const proposalId = idParam ? Number(idParam) : NaN; + const invalidId = !idParam || Number.isNaN(proposalId); + const { proposal, loading, error } = useProposal(invalidId ? -1 : proposalId); + + return ( +
+
+ + Dashboard + + + + Proposal #{idParam ?? ""} + +
+ + {invalidId ? ( +
+ Invalid proposal id. +
+ ) : loading ? ( +
+ Loading proposal details… +
+ ) : error ? ( +
+ {error} +
+ ) : !proposal ? ( +
+ Proposal not found. +
+ ) : ( +
+
+
+
+

+ Proposal #{proposal.id} +

+

+ Send {proposal.amount} {proposal.token} +

+
+
+ {proposal.status} +
+
+ +
+
+

+ Recipient +

+

{proposal.to}

+
+
+

+ Proposed by +

+

+ {proposal.proposer} +

+
+
+ +
+
+

+ Created +

+

+ {proposal.createdAt} +

+
+
+

+ Approvals +

+

+ {proposal.approvals}/{proposal.threshold} +

+
+
+ + {proposal.description && ( +
+

+ Description +

+

+ {proposal.description} +

+
+ )} +
+
+ )} +
+ ); +} From f6e5ed6afb73116df0eeceea6b0f392fc329ebb0 Mon Sep 17 00:00:00 2001 From: uche102 Date: Thu, 25 Jun 2026 13:04:58 +0100 Subject: [PATCH 2/2] ci: fix cargo-audit and cargo-deny installation in workflow --- .github/workflows/contract.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/contract.yml b/.github/workflows/contract.yml index 8b5790e..4bc7446 100644 --- a/.github/workflows/contract.yml +++ b/.github/workflows/contract.yml @@ -20,13 +20,10 @@ jobs: with: targets: wasm32-unknown-unknown - - name: Install cargo-binstall - run: | - curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install.sh | sh - - name: Install cargo-audit and cargo-deny run: | - cargo binstall -y cargo-audit cargo-deny + cargo install cargo-audit --locked + cargo install cargo-deny --locked - name: Run cargo audit run: |