diff --git a/package-lock.json b/package-lock.json index b552c04..a3ba8d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1072,6 +1072,11 @@ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=18.18.0" } @@ -1081,6 +1086,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, + "license": "MIT", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" @@ -7358,7 +7364,7 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ast-types-flow": { + "node_modules/ast-typ": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", @@ -13398,8 +13404,12 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/path-parse": { @@ -14246,6 +14256,7 @@ "engines": { "node": ">= 12.13.0" } + }, "node_modules/redent": { "version": "3.0.0", @@ -15321,6 +15332,13 @@ "node": ">= 0.4" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/src/app/(dashboard)/claim/page.tsx b/src/app/(dashboard)/claim/page.tsx new file mode 100644 index 0000000..ea16ba0 --- /dev/null +++ b/src/app/(dashboard)/claim/page.tsx @@ -0,0 +1,111 @@ +import { useState } from 'react'; +import { AlertTriangle, CheckCircle } from 'lucide-react'; +import { Dispute } from '@/types/dispute'; +import { OpenDisputeModal } from '@/components/modals/OpenDisputeModal'; +import { DisputeVotingCard } from '@/components/claims/DisputeVotingCard'; + + +export default function ClaimDetail() { + const [isDisputeModalOpen, setDisputeModalOpen] = useState(false); + + + const [dispute, setDispute] = useState(null); + + const handleOpenDispute = async (payload: any) => { + + console.log('Opening dispute:', payload); + + + setDispute({ + id: 'dsp_1', + claimId: 'claim_123', + reason: payload.reason, + status: 'VOTING', + proVotes: 0, + conVotes: 0, + totalStaked: payload.initialStake, + createdAt: new Date().toISOString() + }); + }; + + const handleVote = async (id: string, side: string, amount: number) => { + // Call POST /disputes/:id/vote API here + console.log(`Voting ${side} with ${amount}`); + }; + + return ( +
+ + +
+ +
+
+ + +
+
+
+ Climate + 0x1a2b...3c4d +
+

Global average temperatures increased by 1.1°C...

+
+ + + {dispute ? ( + + Dispute Active + + ) : ( + + Verified + + )} +
+ + + {!dispute && ( +
+ + + + +
+ )} + + + {dispute && ( + + )} +
+ + +
+ + +
+ +
+
+ + setDisputeModalOpen(false)} + onSubmit={handleOpenDispute} + /> +
+ ); +} \ No newline at end of file diff --git a/src/components/claims/DisputeVotingCard.tsx b/src/components/claims/DisputeVotingCard.tsx new file mode 100644 index 0000000..4def3e1 --- /dev/null +++ b/src/components/claims/DisputeVotingCard.tsx @@ -0,0 +1,62 @@ +import { useState } from 'react'; + +interface DisputeVotingCardProps { + disputeId: string; + currentStaked: number; + onVote: (disputeId: string, side: 'PRO' | 'CON', amount: number) => Promise; +} + +export const DisputeVotingCard = ({ disputeId, currentStaked, onVote }: DisputeVotingCardProps) => { + const [amount, setAmount] = useState(''); + const [loading, setLoading] = useState(false); + + const handleVote = async (side: 'PRO' | 'CON') => { + if (!amount) return; + setLoading(true); + await onVote(disputeId, side, Number(amount)); + setLoading(false); + setAmount(''); + }; + + return ( +
+
+

+ + + + + Active Dispute Voting +

+ ${currentStaked.toLocaleString()} Staked +
+ +
+ setAmount(e.target.value)} + placeholder="Enter stake amount" + className="w-full rounded-lg border border-zinc-700 bg-zinc-900 p-3 text-white focus:border-red-500 outline-none" + /> +
+ +
+ + +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/features/claim-submission/ClaimSubmissionForm.tsx b/src/components/features/claim-submission/ClaimSubmissionForm.tsx index c40a06a..44cd2f6 100644 --- a/src/components/features/claim-submission/ClaimSubmissionForm.tsx +++ b/src/components/features/claim-submission/ClaimSubmissionForm.tsx @@ -1,3 +1,4 @@ +"use client"; import React, { useState } from "react"; export interface ClaimFormData { diff --git a/src/components/modals/OpenDisputeModal.tsx b/src/components/modals/OpenDisputeModal.tsx new file mode 100644 index 0000000..69ae4f5 --- /dev/null +++ b/src/components/modals/OpenDisputeModal.tsx @@ -0,0 +1,91 @@ +import { useState } from 'react'; +import { X, AlertTriangle } from 'lucide-react'; +import { CreateDisputePayload } from '../../types/dispute'; + +interface OpenDisputeModalProps { + claimId: string; + isOpen: boolean; + onClose: () => void; + onSubmit: (payload: CreateDisputePayload) => Promise; +} + +export const OpenDisputeModal = ({ claimId, isOpen, onClose, onSubmit }: OpenDisputeModalProps) => { + const [reason, setReason] = useState(''); + const [stake, setStake] = useState(''); + const [loading, setLoading] = useState(false); + + if (!isOpen) return null; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + try { + await onSubmit({ claimId, reason, initialStake: Number(stake) }); + onClose(); + } catch (err) { + console.error(err); + } finally { + setLoading(false); + } + }; + + return ( +
+
+
+
+ +

Open Dispute

+
+ +
+ +
+
+ +