create payment roadmap pr a

This commit is contained in:
2026-05-08 20:43:14 +07:00
parent ccb3437e82
commit d4db13778a
10 changed files with 823 additions and 51 deletions
@@ -0,0 +1,32 @@
"use client";
import { useState } from "react";
interface CopyButtonProps {
value: string;
label?: string;
}
export function CopyButton({ value, label = "Salin" }: CopyButtonProps) {
const [copied, setCopied] = useState(false);
async function handleClick() {
try {
await navigator.clipboard.writeText(value);
setCopied(true);
setTimeout(() => setCopied(false), 1500);
} catch {
// ignore — user can copy manually
}
}
return (
<button
type="button"
onClick={handleClick}
className="rounded-lg border border-neutral-200 bg-white px-2.5 py-1 text-xs font-medium text-neutral-600 transition-colors hover:bg-neutral-50"
>
{copied ? "✓ Tersalin" : label}
</button>
);
}
@@ -0,0 +1,50 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { markParticipantPaidAction } from "@/features/booking/actions";
interface MarkPaidButtonProps {
tripId: string;
disabled?: boolean;
}
export function MarkPaidButton({ tripId, disabled }: MarkPaidButtonProps) {
const router = useRouter();
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
async function handleClick() {
setLoading(true);
setError("");
const result = await markParticipantPaidAction(tripId);
setLoading(false);
if (result.error) {
setError(result.error);
return;
}
router.refresh();
}
return (
<div>
{error && (
<div className="mb-3 rounded-xl bg-red-50 px-4 py-3 text-sm font-medium text-red-600">
{error}
</div>
)}
<button
type="button"
onClick={handleClick}
disabled={loading || disabled}
className="w-full rounded-xl bg-primary-600 py-3 text-sm font-bold text-white shadow-lg shadow-primary-600/20 transition-colors hover:bg-primary-700 disabled:cursor-not-allowed disabled:opacity-50"
>
{loading ? "Memproses..." : "Saya sudah bayar"}
</button>
<p className="mt-2 text-center text-[11px] text-neutral-500">
Tekan setelah kamu transfer ke rekening di atas. Organizer akan cek &
konfirmasi pembayaran kamu.
</p>
</div>
);
}