Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
28efc38
fix(cache): clear min stake entries during invalidate-all
Mosas2000 Apr 10, 2026
3cfa5ae
test(vitest): align @ alias with src root
Mosas2000 Apr 11, 2026
d87b9d9
test(jsdom): add matchMedia and scrollIntoView shims
Mosas2000 Apr 11, 2026
57fe3df
test(app): fix hydration test mocks and module paths
Mosas2000 Apr 11, 2026
9fc7fdb
test(app): stabilize command palette integration tests
Mosas2000 Apr 11, 2026
e207f3a
chore(frontend): trim ui imports
Mosas2000 Apr 15, 2026
5c94520
chore(frontend): clear lint tail
Mosas2000 Apr 15, 2026
04b72aa
chore(frontend): clean notification center
Mosas2000 Apr 15, 2026
8cdf5d6
chore(frontend): tidy remaining dashboards
Mosas2000 Apr 15, 2026
4da9fa2
chore(frontend): tidy stateful widgets
Mosas2000 Apr 15, 2026
5209ca2
chore(frontend): trim proposal flow ui
Mosas2000 Apr 15, 2026
018bbba
chore(frontend): trim voting widgets
Mosas2000 Apr 15, 2026
b1847d9
chore(frontend): finish analytics cleanup
Mosas2000 Apr 16, 2026
c8c01f4
chore(frontend): clean dashboard components
Mosas2000 Apr 16, 2026
6b4c525
chore(frontend): simplify shell components
Mosas2000 Apr 16, 2026
6f268cb
chore(frontend): clean onboarding and layout
Mosas2000 Apr 16, 2026
f5dae18
chore(frontend): clean activity widgets
Mosas2000 Apr 16, 2026
08750ee
chore(frontend): fix budget dashboard
Mosas2000 Apr 16, 2026
e20725e
Refine app shell lint
Mosas2000 Apr 16, 2026
0278ba5
Refine analytics charts
Mosas2000 Apr 16, 2026
9ca20f1
Trim remaining lint tail
Mosas2000 Apr 16, 2026
e048edd
Merge origin/main into feature branch
Mosas2000 Apr 16, 2026
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
2 changes: 0 additions & 2 deletions frontend/components/CommentInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ interface CommentInputProps {
}

export function CommentInput({
proposalId,
onSubmit,
isReply = false,
onCancel,
Expand All @@ -22,7 +21,6 @@ export function CommentInput({
const { userSession } = useConnect();
const [content, setContent] = useState('');
const [error, setError] = useState<string | null>(null);
void proposalId;

const handleSubmit = () => {
if (!userSession) {
Expand Down
5 changes: 4 additions & 1 deletion frontend/components/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ interface CommentsProps {

export default function Comments({ proposalId, userAddress }: CommentsProps) {
const [comments, setComments] = useState<Comment[]>(() => {
if (typeof window === 'undefined') return [];
if (typeof window === 'undefined') {
return [];
}

const stored = localStorage.getItem(`comments-${proposalId}`);
return stored ? JSON.parse(stored) : [];
});
Expand Down
134 changes: 90 additions & 44 deletions frontend/components/MilestoneTracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,99 @@ interface MilestoneTrackerProps {
}

export default function MilestoneTracker({ proposalId, totalFunding }: MilestoneTrackerProps) {
const defaultMilestones: Milestone[] = [
{
id: 1,
name: 'Project Kickoff',
description: 'Initial setup and planning phase',
percentage: 25,
fundAmount: totalFunding * 0.25,
status: 'completed',
verifications: [],
deliverables: ['Project plan', 'Technical specification']
},
{
id: 2,
name: 'Development Phase 1',
description: 'Core functionality implementation',
percentage: 50,
fundAmount: totalFunding * 0.25,
status: 'in-progress',
verifications: [],
deliverables: ['Working prototype', 'Test coverage']
},
{
id: 3,
name: 'Development Phase 2',
description: 'Advanced features and integration',
percentage: 75,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Feature complete', 'Integration tests']
},
{
id: 4,
name: 'Launch & Delivery',
description: 'Final testing and deployment',
percentage: 100,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Production deployment', 'Documentation']
const [milestones, setMilestones] = useState<Milestone[]>(() => {
if (typeof window === 'undefined') {
return [
{
id: 1,
name: 'Project Kickoff',
description: 'Initial setup and planning phase',
percentage: 25,
fundAmount: totalFunding * 0.25,
status: 'completed',
verifications: [],
deliverables: ['Project plan', 'Technical specification']
},
{
id: 2,
name: 'Development Phase 1',
description: 'Core functionality implementation',
percentage: 50,
fundAmount: totalFunding * 0.25,
status: 'in-progress',
verifications: [],
deliverables: ['Working prototype', 'Test coverage']
},
{
id: 3,
name: 'Development Phase 2',
description: 'Advanced features and integration',
percentage: 75,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Feature complete', 'Integration tests']
},
{
id: 4,
name: 'Launch & Delivery',
description: 'Final testing and deployment',
percentage: 100,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Production deployment', 'Documentation']
}
];
}
];

const [milestones, setMilestones] = useState<Milestone[]>(() => {
if (typeof window === 'undefined') return defaultMilestones;
const stored = localStorage.getItem(`proposal-${proposalId}-milestones`);
return stored ? JSON.parse(stored) : defaultMilestones;
if (stored) {
return JSON.parse(stored);
}

return [
{
id: 1,
name: 'Project Kickoff',
description: 'Initial setup and planning phase',
percentage: 25,
fundAmount: totalFunding * 0.25,
status: 'completed',
verifications: [],
deliverables: ['Project plan', 'Technical specification']
},
{
id: 2,
name: 'Development Phase 1',
description: 'Core functionality implementation',
percentage: 50,
fundAmount: totalFunding * 0.25,
status: 'in-progress',
verifications: [],
deliverables: ['Working prototype', 'Test coverage']
},
{
id: 3,
name: 'Development Phase 2',
description: 'Advanced features and integration',
percentage: 75,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Feature complete', 'Integration tests']
},
{
id: 4,
name: 'Launch & Delivery',
description: 'Final testing and deployment',
percentage: 100,
fundAmount: totalFunding * 0.25,
status: 'pending',
verifications: [],
deliverables: ['Production deployment', 'Documentation']
}
];
});

const [selectedMilestone, setSelectedMilestone] = useState<Milestone | null>(null);
Expand Down
36 changes: 20 additions & 16 deletions frontend/components/MultiSigTreasury.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ interface MultiSigConfig {
}

export default function MultiSigTreasury() {
const now = Date.parse(new Date().toISOString());
const [currentTime] = useState(() => Date.now());
const baseTime = currentTime;

const [config, setConfig] = useState<MultiSigConfig>({
totalSigners: 5,
requiredSignatures: 3,
Expand All @@ -43,7 +45,7 @@ export default function MultiSigTreasury() {
timelock: 48
});

const [transactions, setTransactions] = useState<Transaction[]>([
const [transactions, setTransactions] = useState<Transaction[]>(() => [
{
id: 1,
type: 'withdrawal',
Expand All @@ -54,16 +56,16 @@ export default function MultiSigTreasury() {
requiredSignatures: 3,
currentSignatures: 2,
signers: [
{ address: 'SP9XYZ...123', name: 'Alice (Treasury Manager)', signed: true, timestamp: now - 2 * 60 * 60 * 1000 },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: now - 1 * 60 * 60 * 1000 },
{ address: 'SP9XYZ...123', name: 'Alice (Treasury Manager)', signed: true, timestamp: baseTime - 2 * 60 * 60 * 1000 },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: baseTime - 1 * 60 * 60 * 1000 },
{ address: 'SP7DEF...789', name: 'Carol (Admin)', signed: false },
{ address: 'SP6GHI...012', name: 'Dave (Auditor)', signed: false },
{ address: 'SP5JKL...345', name: 'Eve (Advisor)', signed: false }
],
status: 'pending',
createdAt: now - 3 * 60 * 60 * 1000,
createdAt: baseTime - 3 * 60 * 60 * 1000,
threshold: 75000,
deadline: now + 45 * 60 * 60 * 1000
deadline: baseTime + 45 * 60 * 60 * 1000
},
{
id: 2,
Expand All @@ -75,15 +77,15 @@ export default function MultiSigTreasury() {
currentSignatures: 1,
signers: [
{ address: 'SP9XYZ...123', name: 'Alice (Treasury Manager)', signed: false },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: now - 12 * 60 * 60 * 1000 },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: baseTime - 12 * 60 * 60 * 1000 },
{ address: 'SP7DEF...789', name: 'Carol (Admin)', signed: false },
{ address: 'SP6GHI...012', name: 'Dave (Auditor)', signed: false },
{ address: 'SP5JKL...345', name: 'Eve (Advisor)', signed: false }
],
status: 'pending',
createdAt: now - 24 * 60 * 60 * 1000,
createdAt: baseTime - 24 * 60 * 60 * 1000,
threshold: 50000,
deadline: now + 24 * 60 * 60 * 1000
deadline: baseTime + 24 * 60 * 60 * 1000
},
{
id: 3,
Expand All @@ -95,20 +97,21 @@ export default function MultiSigTreasury() {
requiredSignatures: 3,
currentSignatures: 3,
signers: [
{ address: 'SP9XYZ...123', name: 'Alice (Treasury Manager)', signed: true, timestamp: now - 48 * 60 * 60 * 1000 },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: now - 46 * 60 * 60 * 1000 },
{ address: 'SP7DEF...789', name: 'Carol (Admin)', signed: true, timestamp: now - 45 * 60 * 60 * 1000 },
{ address: 'SP9XYZ...123', name: 'Alice (Treasury Manager)', signed: true, timestamp: baseTime - 48 * 60 * 60 * 1000 },
{ address: 'SP8ABC...456', name: 'Bob (Finance Lead)', signed: true, timestamp: baseTime - 46 * 60 * 60 * 1000 },
{ address: 'SP7DEF...789', name: 'Carol (Admin)', signed: true, timestamp: baseTime - 45 * 60 * 60 * 1000 },
{ address: 'SP6GHI...012', name: 'Dave (Auditor)', signed: false },
{ address: 'SP5JKL...345', name: 'Eve (Advisor)', signed: false }
],
status: 'executed',
createdAt: now - 72 * 60 * 60 * 1000,
createdAt: baseTime - 72 * 60 * 60 * 1000,
threshold: 50000,
deadline: now - 24 * 60 * 60 * 1000
deadline: baseTime - 24 * 60 * 60 * 1000
}
]);

const [showConfigModal, setShowConfigModal] = useState(false);
const [, setShowNewTxModal] = useState(false);
const [, setShowConfigModal] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const [filterStatus, setFilterStatus] = useState<'all' | Transaction['status']>('all');

Expand Down Expand Up @@ -180,7 +183,7 @@ export default function MultiSigTreasury() {
};

const formatTimeRemaining = (deadline: number) => {
const diff = deadline - now;
const diff = deadline - currentTime;
const hours = Math.floor(diff / (1000 * 60 * 60));
const days = Math.floor(hours / 24);

Expand Down Expand Up @@ -221,6 +224,7 @@ export default function MultiSigTreasury() {
</button>
)}
<button
onClick={() => setShowNewTxModal(true)}
disabled={isPaused}
className="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700
disabled:bg-gray-400 disabled:cursor-not-allowed"
Expand Down
5 changes: 1 addition & 4 deletions frontend/components/MultisigFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@ const signers = [
];

export default function MultisigFlow() {
const signedCount = signers.filter(s => s.status === 'signed').length;
const progressText = `${signedCount}/${signers.length} signatures collected`;

return (
<div className="p-8 bg-slate-900/50 backdrop-blur-xl border border-white/10 rounded-[40px] overflow-hidden">
<div className="flex justify-between items-start mb-10">
<div>
<h3 className="text-xl font-black uppercase tracking-tight text-white mb-1">Execution Guard</h3>
<p className="text-[10px] font-bold text-slate-500 uppercase">{progressText}</p>
<p className="text-[10px] font-bold text-slate-500 uppercase">2/3 Multi-signature verification required</p>
</div>
<Shield className="w-8 h-8 text-orange-600" />
</div>
Expand Down
41 changes: 22 additions & 19 deletions frontend/components/NotificationHub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,29 @@ interface Notification {
}

export default function NotificationHub() {
const now = Date.parse(new Date().toISOString());
const [isOpen, setIsOpen] = useState(false);
const [notifications, setNotifications] = useState<Notification[]>([
{
id: '1',
title: 'Proposal Funded',
message: 'Your proposal "Stacks Wallet Integration" has reached the funding threshold!',
type: 'success',
timestamp: new Date(now),
read: false
},
{
id: '2',
title: 'New Governance Vote',
message: 'A new platform-wide vote on Treasury Allocation is live.',
type: 'governance',
timestamp: new Date(now - 3600000),
read: false
}
]);
const [notifications, setNotifications] = useState<Notification[]>(() => {
const baseTime = Date.now();

return [
{
id: '1',
title: 'Proposal Funded',
message: 'Your proposal "Stacks Wallet Integration" has reached the funding threshold!',
type: 'success',
timestamp: new Date(baseTime),
read: false
},
{
id: '2',
title: 'New Governance Vote',
message: 'A new platform-wide vote on Treasury Allocation is live.',
type: 'governance',
timestamp: new Date(baseTime - 3600000),
read: false
}
];
});

const unreadCount = notifications.filter(n => !n.read).length;

Expand Down
2 changes: 1 addition & 1 deletion frontend/components/ParticipationHeatmap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Calendar } from 'lucide-react';

export default function ParticipationHeatmap() {
// Simulating 7 days x 12 intervals
const grid = Array.from({ length: 84 }).map(() => Math.random());
const grid = Array.from({ length: 84 }, (_, index) => ((index * 37) % 100) / 100);

return (
<div className="p-8 bg-slate-900/50 backdrop-blur-xl border border-white/10 rounded-[40px] overflow-hidden">
Expand Down
Loading
Loading