mirror of
https://github.com/domfelipe/mika-agent-assist.git
synced 2026-08-07 11:56:45 +00:00
Changes
Co-authored-by: domfelipe <53182096+domfelipe@users.noreply.github.com>
This commit is contained in:
parent
8056aaab35
commit
c0106e1b9e
1 changed files with 56 additions and 14 deletions
|
|
@ -1,14 +1,14 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
Check,
|
Check,
|
||||||
Copy,
|
Copy,
|
||||||
ExternalLink,
|
|
||||||
Loader2,
|
Loader2,
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
|
MessageCircle,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
|
@ -30,16 +30,24 @@ interface Props {
|
||||||
onSkip: () => void;
|
onSkip: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Phase = "configure" | "awaiting_start" | "captured";
|
||||||
|
|
||||||
export function BotFatherWizard({ agentName, fullName, onActivated, onSkip }: Props) {
|
export function BotFatherWizard({ agentName, fullName, onActivated, onSkip }: Props) {
|
||||||
|
const [phase, setPhase] = useState<Phase>("configure");
|
||||||
const [step1Done, setStep1Done] = useState(false);
|
const [step1Done, setStep1Done] = useState(false);
|
||||||
const [step2Done, setStep2Done] = useState(false);
|
const [step2Done, setStep2Done] = useState(false);
|
||||||
const [step3Done, setStep3Done] = useState(false);
|
const [step3Done, setStep3Done] = useState(false);
|
||||||
const [token, setToken] = useState("");
|
const [token, setToken] = useState("");
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||||
|
const [validatedBot, setValidatedBot] = useState<{
|
||||||
|
bot_username: string;
|
||||||
|
bot_name: string;
|
||||||
|
bot_id: number;
|
||||||
|
} | null>(null);
|
||||||
|
const pollRef = useRef<number | null>(null);
|
||||||
|
|
||||||
const suggestedUsername = useMemo(() => {
|
const suggestedUsername = useMemo(() => {
|
||||||
// base do agent_name; cai pro firstName se não der
|
|
||||||
const base = sanitizeForUsername(agentName).replace(/^mikade/, "mika");
|
const base = sanitizeForUsername(agentName).replace(/^mikade/, "mika");
|
||||||
if (base.length >= 5) {
|
if (base.length >= 5) {
|
||||||
const trimmed = base.slice(0, 28);
|
const trimmed = base.slice(0, 28);
|
||||||
|
|
@ -55,16 +63,6 @@ export function BotFatherWizard({ agentName, fullName, onActivated, onSkip }: Pr
|
||||||
setStep1Done(true);
|
setStep1Done(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyToClipboard(value: string, onDone: () => void) {
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(value);
|
|
||||||
toast.success("Copiado!");
|
|
||||||
onDone();
|
|
||||||
} catch {
|
|
||||||
toast.error("Não foi possível copiar.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleActivate() {
|
async function handleActivate() {
|
||||||
if (!tokenValid) return;
|
if (!tokenValid) return;
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
@ -82,9 +80,53 @@ export function BotFatherWizard({ agentName, fullName, onActivated, onSkip }: Pr
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onActivated(data);
|
setSubmitting(false);
|
||||||
|
setValidatedBot(data);
|
||||||
|
setPhase("awaiting_start");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleOpenMyBot() {
|
||||||
|
if (!validatedBot?.bot_username) return;
|
||||||
|
window.open(
|
||||||
|
`https://t.me/${validatedBot.bot_username}`,
|
||||||
|
"_blank",
|
||||||
|
"noopener,noreferrer",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polling: enquanto phase === awaiting_start, chama capture-telegram-owner a cada 2.5s
|
||||||
|
useEffect(() => {
|
||||||
|
if (phase !== "awaiting_start") return;
|
||||||
|
let cancelled = false;
|
||||||
|
|
||||||
|
async function tick() {
|
||||||
|
if (cancelled) return;
|
||||||
|
const { data, error } = await invokeFunction<{
|
||||||
|
found: boolean;
|
||||||
|
chat_id?: number;
|
||||||
|
first_name?: string;
|
||||||
|
bot_username?: string;
|
||||||
|
}>("capture-telegram-owner", {});
|
||||||
|
if (cancelled) return;
|
||||||
|
if (error) {
|
||||||
|
console.warn("capture-telegram-owner error", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data?.found && validatedBot) {
|
||||||
|
setPhase("captured");
|
||||||
|
setTimeout(() => onActivated(validatedBot), 1400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tick();
|
||||||
|
pollRef.current = window.setInterval(tick, 2500);
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
if (pollRef.current) window.clearInterval(pollRef.current);
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [phase, validatedBot]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-8 lg:grid-cols-2 lg:gap-10 items-start">
|
<div className="grid gap-8 lg:grid-cols-2 lg:gap-10 items-start">
|
||||||
{/* COLUNA ESQUERDA — passos */}
|
{/* COLUNA ESQUERDA — passos */}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue