Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/StageChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const chipClasses: Record<StageChipKind, string> = {
thread: "bg-panel-alt text-muted",
courts: "bg-[color:var(--accent-warm)]/15 text-[var(--accent-warm)]",
faction: "bg-panel-alt text-muted",
system: "bg-[color:var(--danger)]/12 text-[color:var(--danger)]",
};

const hintByKind: Partial<Record<StageChipKind, string>> = {
Expand Down
12 changes: 9 additions & 3 deletions src/pages/courts/Courts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,16 @@ const Courts: React.FC = () => {
</Card>
)}
</div>

<div className="pointer-events-none absolute inset-0 z-20 grid place-items-center p-6">
<h2 className="text-center text-4xl font-semibold text-text sm:text-5xl lg:text-6xl">
coming sooner than you think...
</h2>
<Card className="max-w-md border-dashed bg-panel/90 px-6 py-5 text-center shadow-lg backdrop-blur">
<p className="text-sm tracking-[0.24em] text-muted uppercase">
Courts
</p>
<p className="mt-3 text-xl font-semibold text-foreground">
coming sooner than you think...
</p>
</Card>
</div>
</div>
);
Expand Down
10 changes: 9 additions & 1 deletion src/pages/feed/Feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async function loadUrgentFeedItems(input: {
limit: number;
isGovernorActive: boolean;
}): Promise<FeedItemDto[]> {
const [base, pool, vote, build, invites] = await Promise.all([
const [base, pool, vote, build, invites, system] = await Promise.all([
apiFeed({ chambers: input.chambers, limit: input.limit }),
apiFeed({
stage: "pool",
Expand All @@ -178,6 +178,13 @@ async function loadUrgentFeedItems(input: {
limit: FEED_MIN_PAGE_SIZE,
})
: Promise.resolve({ items: [] as FeedItemDto[] }),
input.address
? apiFeed({
actor: input.address,
stage: "system",
limit: URGENT_STAGE_LIMIT,
})
: Promise.resolve({ items: [] as FeedItemDto[] }),
]);

return toUrgentItems(
Expand All @@ -187,6 +194,7 @@ async function loadUrgentFeedItems(input: {
...vote.items,
...build.items,
...invites.items,
...system.items,
],
input.isGovernorActive,
input.address,
Expand Down
66 changes: 65 additions & 1 deletion src/pages/invision/Invision.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,18 @@ const Invision: React.FC = () => {
const secondaryGovernanceMetrics = (
invision?.governanceState.metrics ?? []
).slice(3);
const stability = invision?.stability ?? null;
const stabilityToneClass = (tone: "positive" | "watch" | "critical") => {
if (tone === "critical") return "text-destructive";
if (tone === "watch") return "text-primary";
return "text-text";
};

return (
<div className="flex flex-col gap-5">
<div className="flex flex-col gap-5">
<PageHint pageId="invision" />
{invision === null ? (
{invision === null && !loadError ? (
<Card className="border-dashed px-4 py-6 text-center text-sm text-muted">
Loading Invision…
</Card>
Expand Down Expand Up @@ -145,6 +151,64 @@ const Invision: React.FC = () => {
</Card>
) : null}

{stability ? (
<Card>
<CardHeader className="pb-2">
<CardTitle>Stability engine</CardTitle>
</CardHeader>
<CardContent className="space-y-4 text-sm text-text">
<div className="grid gap-3 sm:grid-cols-3">
<div className="rounded-xl border border-border px-3 py-3">
<Kicker>Band</Kicker>
<p className="text-lg font-semibold text-text">
{stability.band}
</p>
</div>
<div className="rounded-xl border border-border px-3 py-3">
<Kicker>Confidence</Kicker>
<p className="text-lg font-semibold text-text">
{stability.confidence}% · {stability.confidenceBand}
</p>
</div>
<div className="rounded-xl border border-border px-3 py-3">
<Kicker>Window</Kicker>
<p className="text-lg font-semibold text-text">
{stability.windowLabel}
</p>
</div>
</div>

<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
{stability.components.map((component) => (
<div
key={component.label}
className="rounded-xl border border-border px-3 py-3"
>
<Kicker>{component.label}</Kicker>
<p
className={`text-lg font-semibold ${stabilityToneClass(component.tone)}`}
>
{component.score}%
</p>
<p className="text-xs text-muted">{component.detail}</p>
</div>
))}
</div>

{stability.capsApplied.length > 0 ? (
<div className="rounded-xl border border-border px-3 py-3">
<Kicker>Active caps</Kicker>
<div className="space-y-1 text-xs text-muted">
{stability.capsApplied.map((cap) => (
<p key={cap}>{cap}</p>
))}
</div>
</div>
) : null}
</CardContent>
</Card>
) : null}

<SearchBar
value={search}
onChange={(e) => setSearch(e.target.value)}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/proposals/proposalCreation/presets/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ export const PROPOSAL_PRESETS: ProposalPreset[] = [
},
{
id: "project.dao_core.governing-threshold.policy",
label: "Governing threshhold",
label: "Governing threshold",
description: "Governing thresholds and quorum constraints.",
templateId: "project",
proposalType: "dao-core",
Expand Down
16 changes: 16 additions & 0 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,21 @@ export type InvisionGovernanceStateDto = {
label: string;
metrics: InvisionGovernanceMetricDto[];
};
export type InvisionStabilityComponentDto = {
label: string;
score: number;
detail: string;
tone: "positive" | "watch" | "critical";
};
export type InvisionStabilityDto = {
score: number;
band: "Stable" | "Watch" | "Unstable";
confidence: number;
confidenceBand: "Low" | "Medium" | "High";
windowLabel: string;
capsApplied: string[];
components: InvisionStabilityComponentDto[];
};
export type InvisionEconomicIndicatorDto = {
label: string;
value: string;
Expand All @@ -288,6 +303,7 @@ export type InvisionChamberProposalDto = {
};
export type GetInvisionResponse = {
governanceState: InvisionGovernanceStateDto;
stability: InvisionStabilityDto;
economicIndicators: InvisionEconomicIndicatorDto[];
riskSignals: InvisionRiskSignalDto[];
chamberProposals: InvisionChamberProposalDto[];
Expand Down
6 changes: 5 additions & 1 deletion src/types/stages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const feedStages = [
"thread",
"courts",
"faction",
"system",
] as const;

export type FeedStage = (typeof feedStages)[number];
Expand All @@ -28,7 +29,8 @@ export type StageChipKind =
| "passed"
| "thread"
| "courts"
| "faction";
| "faction"
| "system";

export const stageToChipKind = {
pool: "proposal_pool",
Expand All @@ -39,6 +41,7 @@ export const stageToChipKind = {
thread: "thread",
courts: "courts",
faction: "faction",
system: "system",
} as const satisfies Record<Stage, StageChipKind>;

export const stageLabel = {
Expand All @@ -50,6 +53,7 @@ export const stageLabel = {
thread: "Thread",
courts: "Courts",
faction: "Faction",
system: "System",
} as const satisfies Record<Stage, string>;

export const proposalStageToChipKind: Record<ProposalStage, StageChipKind> =
Expand Down