You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

110 lines
3.1 KiB

"use client";
import { useState } from "react";
import { useI18n } from "@/translations/provider";
import { LoadingSkeleton } from "./loading-skeleton";
import { LoadingBorderSpinner } from "@/components/ui/loading-border-spinner";
type SwipeButtonProps = {
onSuccess: () => void | Promise<void>;
onCancel?: () => void;
text: string;
cancelText?: string;
disabled?: boolean;
isLoading?: boolean;
isSubmitting?: boolean;
theme?: "default" | "green" | "pink";
};
export function SwipeButton({
onSuccess,
onCancel,
text,
cancelText,
disabled = false,
isLoading = false,
isSubmitting = false,
theme = "default",
}: SwipeButtonProps) {
const { dictionary: t } = useI18n();
const [internalSubmitting, setInternalSubmitting] = useState(false);
if (isLoading) {
if (onCancel) {
return (
<div className="flex w-full items-center gap-3">
<LoadingSkeleton className="flex-1 h-[52px] rounded-[11px]" />
<LoadingSkeleton className="flex-1 h-[52px] rounded-[11px]" />
</div>
);
}
return (
<div className="w-full flex">
<LoadingSkeleton className="w-full h-[52px] rounded-[11px]" />
</div>
);
}
const busy = isSubmitting || internalSubmitting;
const handleClick = async () => {
if (disabled || busy) return;
setInternalSubmitting(true);
try {
await onSuccess();
} finally {
setInternalSubmitting(false);
}
};
const cancelLabel = cancelText || t?.["Cancel"] || "Cancel";
const buttonBg =
theme === "green"
? "bg-[#00AC78]"
: theme === "pink"
? "bg-gradient-to-r from-[#FF6687] to-[#FF456C] shadow-[0_8px_16px_rgba(255,69,108,0.25)]"
: "bg-[#F0445B]";
const actionButton = (
<button
type="button"
disabled={disabled || busy}
onClick={handleClick}
className={`flex-1 min-w-0 h-[52px] rounded-[11px] px-3 ${buttonBg} text-white font-semibold group-16 flex items-center justify-center cursor-pointer transition-all active:scale-[0.98] hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed`}
>
{busy ? (
<LoadingBorderSpinner size="sm" variant="white" />
) : (
<span className="block w-full min-w-0 max-w-full truncate text-center">
{text}
</span>
)}
</button>
);
if (onCancel) {
return (
<div className="flex w-full items-center gap-3">
{/* Cancel Button */}
<button
type="button"
disabled={busy}
onClick={onCancel}
className="flex-1 min-w-0 h-[52px] rounded-[11px] px-3 border border-[#8B8B8B] bg-transparent text-[#8B8B8B] font-semibold group-16 flex items-center justify-center cursor-pointer transition-all active:scale-[0.98] hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
>
<span className="block w-full min-w-0 max-w-full truncate text-center">
{cancelLabel}
</span>
</button>
{/* Action Button */}
{actionButton}
</div>
);
}
// Single Button full width
return <div className="w-full flex">{actionButton}</div>;
}
export default SwipeButton;