fix(frontend): feedback button copy (#11246)

## Changes 🏗️

<img width="800" height="827" alt="Screenshot 2025-10-24 at 17 45 48"
src="https://github.com/user-attachments/assets/ab18361e-6c58-43e9-bea6-c9172d06c0e7"
/>

- Shows the text `Give feedback` so the button is more explicit 🏁 
- Refactor the component to stick to [new code
conventions](https://github.com/Significant-Gravitas/AutoGPT/blob/master/autogpt_platform/frontend/CONTRIBUTING.md)

## Checklist 📋

### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  - [x] Load the app
  - [x] Check the Tally popup button copy
  - [x] The button still works
This commit is contained in:
Ubbe
2025-10-28 14:00:33 +04:00
committed by GitHub
parent 377657f8a1
commit d8a5780ea2
2 changed files with 147 additions and 127 deletions

View File

@@ -1,155 +1,49 @@
"use client";
import React, { useEffect, useState } from "react";
import { Button } from "../../__legacy__/ui/button";
import React from "react";
import { QuestionMarkCircledIcon } from "@radix-ui/react-icons";
import { useRouter, usePathname } from "next/navigation";
import * as Sentry from "@sentry/nextjs";
import { getCurrentUser } from "@/lib/supabase/actions";
import { useTallyPopup } from "./useTallyPopup";
import { Button } from "@/components/atoms/Button/Button";
const TallyPopupSimple = () => {
const [isFormVisible, setIsFormVisible] = useState(false);
const [sentryReplayId, setSentryReplayId] = useState("");
const [replayUrl, setReplayUrl] = useState("");
const [pageUrl, setPageUrl] = useState("");
const [userAgent, setUserAgent] = useState("");
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
// const [userId, setUserId] = useState<string>("");
const [userEmail, setUserEmail] = useState<string>("");
const router = useRouter();
const pathname = usePathname();
export function TallyPopupSimple() {
const { state, handlers } = useTallyPopup();
const [show_tutorial, setShowTutorial] = useState(false);
useEffect(() => {
setShowTutorial(pathname.includes("build"));
}, [pathname]);
useEffect(() => {
// Set client-side values
if (typeof window !== "undefined") {
setPageUrl(window.location.href);
setUserAgent(window.navigator.userAgent);
const replay = Sentry.getReplay();
if (replay) {
const replayId = replay.getReplayId();
if (replayId) {
setSentryReplayId(replayId);
const orgSlug = "significant-gravitas";
setReplayUrl(`https://${orgSlug}.sentry.io/replays/${replayId}/`);
}
}
}
}, [pathname]);
useEffect(() => {
// Check authentication status using server action (works with httpOnly cookies)
getCurrentUser().then(({ user }) => {
setIsAuthenticated(user != null);
// setUserId(user?.id || "");
setUserEmail(user?.email || "");
});
}, [pathname]);
useEffect(() => {
// Load Tally script
const script = document.createElement("script");
script.src = "https://tally.so/widgets/embed.js";
script.async = true;
document.head.appendChild(script);
// Setup event listeners for Tally events
const handleTallyMessage = (event: MessageEvent) => {
if (typeof event.data === "string") {
// Ignore iframe-resizer messages
if (
event.data.startsWith("[iFrameSize") ||
event.data.startsWith("[iFrameResizer")
) {
return;
}
try {
const data = JSON.parse(event.data);
// Only process Tally events
if (!data.event?.startsWith("Tally.")) {
return;
}
if (data.event === "Tally.FormLoaded") {
setIsFormVisible(true);
// Flush Sentry replay when form opens
if (typeof window !== "undefined") {
const replay = Sentry.getReplay();
if (replay) {
replay.flush();
}
}
} else if (data.event === "Tally.PopupClosed") {
setIsFormVisible(false);
}
} catch (error) {
// Only log errors for messages we care about
if (event.data.includes("Tally")) {
console.error("Error parsing Tally message:", error);
}
}
}
};
window.addEventListener("message", handleTallyMessage);
return () => {
document.head.removeChild(script);
window.removeEventListener("message", handleTallyMessage);
};
}, []);
if (isFormVisible) {
if (state.isFormVisible) {
return null;
}
const resetTutorial = () => {
router.push("/build?resetTutorial=true");
};
return (
<div className="fixed bottom-1 right-24 z-20 hidden select-none items-center gap-4 p-3 transition-all duration-300 ease-in-out md:flex">
{show_tutorial && (
{state.showTutorial && (
<Button
variant="default"
onClick={resetTutorial}
variant="primary"
onClick={handlers.handleResetTutorial}
className="mb-0 h-14 w-28 rounded-2xl bg-[rgba(65,65,64,1)] text-left font-sans text-lg font-medium leading-6"
>
Tutorial
</Button>
)}
<Button
className="h-14 w-14 rounded-full bg-[rgba(65,65,64,1)]"
variant="default"
variant="primary"
data-tally-open="3yx2L0"
data-tally-emoji-text="👋"
data-tally-emoji-animation="wave"
data-sentry-replay-id={sentryReplayId || "not-initialized"}
data-sentry-replay-url={replayUrl || "not-initialized"}
data-user-agent={userAgent}
data-page-url={pageUrl}
data-sentry-replay-id={state.sentryReplayId || "not-initialized"}
data-sentry-replay-url={state.replayUrl || "not-initialized"}
data-user-agent={state.userAgent}
data-page-url={state.pageUrl}
data-is-authenticated={
isAuthenticated === null ? "unknown" : String(isAuthenticated)
state.isAuthenticated === null
? "unknown"
: String(state.isAuthenticated)
}
data-email={userEmail || "not-authenticated"}
// data-user-id={userId || "not-authenticated"}
data-email={state.userEmail || "not-authenticated"}
>
<QuestionMarkCircledIcon className="h-14 w-14" />
<span className="sr-only">Reach Out</span>
<QuestionMarkCircledIcon className="h-6 w-6" />
<span className="">Give Feedback</span>
</Button>
</div>
);
};
}
export default TallyPopupSimple;

View File

@@ -0,0 +1,126 @@
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import * as Sentry from "@sentry/nextjs";
import { getCurrentUser } from "@/lib/supabase/actions";
export function useTallyPopup() {
const [isFormVisible, setIsFormVisible] = useState(false);
const [sentryReplayId, setSentryReplayId] = useState("");
const [replayUrl, setReplayUrl] = useState("");
const [pageUrl, setPageUrl] = useState("");
const [userAgent, setUserAgent] = useState("");
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
const [userEmail, setUserEmail] = useState<string>("");
const router = useRouter();
const pathname = usePathname();
const [showTutorial, setShowTutorial] = useState(false);
useEffect(() => {
setShowTutorial(pathname.includes("build"));
}, [pathname]);
useEffect(() => {
// Set client-side values
if (typeof window !== "undefined") {
setPageUrl(window.location.href);
setUserAgent(window.navigator.userAgent);
const replay = Sentry.getReplay();
if (replay) {
const replayId = replay.getReplayId();
if (replayId) {
setSentryReplayId(replayId);
const orgSlug = "significant-gravitas";
setReplayUrl(`https://${orgSlug}.sentry.io/replays/${replayId}/`);
}
}
}
}, [pathname]);
useEffect(() => {
// Check authentication status using server action (works with httpOnly cookies)
getCurrentUser().then(({ user }) => {
setIsAuthenticated(user != null);
setUserEmail(user?.email || "");
});
}, [pathname]);
useEffect(() => {
// Load Tally script
const script = document.createElement("script");
script.src = "https://tally.so/widgets/embed.js";
script.async = true;
document.head.appendChild(script);
// Setup event listeners for Tally events
const handleTallyMessage = (event: MessageEvent) => {
if (typeof event.data === "string") {
// Ignore iframe-resizer messages
if (
event.data.startsWith("[iFrameSize") ||
event.data.startsWith("[iFrameResizer")
) {
return;
}
try {
const data = JSON.parse(event.data);
// Only process Tally events
if (!data.event?.startsWith("Tally.")) {
return;
}
if (data.event === "Tally.FormLoaded") {
setIsFormVisible(true);
// Flush Sentry replay when form opens
if (typeof window !== "undefined") {
const replay = Sentry.getReplay();
if (replay) {
replay.flush();
}
}
} else if (data.event === "Tally.PopupClosed") {
setIsFormVisible(false);
}
} catch (error) {
// Only log errors for messages we care about
if (event.data.includes("Tally")) {
console.error("Error parsing Tally message:", error);
}
}
}
};
window.addEventListener("message", handleTallyMessage);
return () => {
document.head.removeChild(script);
window.removeEventListener("message", handleTallyMessage);
};
}, []);
function handleResetTutorial() {
router.push("/build?resetTutorial=true");
}
return {
state: {
showTutorial,
sentryReplayId,
replayUrl,
pageUrl,
userAgent,
isAuthenticated,
isFormVisible,
userEmail,
},
handlers: {
handleResetTutorial,
},
};
}