mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-06 22:32:16 +00:00
docs: update feedback form (#11717)
This PR forces the user to enter a reason/explanation before submitting a negative feedback. Negative feedback without an explanation is not actionable.
This commit is contained in:
@@ -1,20 +1,43 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useState, FormEvent } from 'react';
|
||||
import { mixpanelClient } from '@/utils/mixpanel';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { ThumbsUp, ThumbsDown } from 'lucide-react';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
export function Feedback() {
|
||||
const MAX_CHARS = 500;
|
||||
const pathname = usePathname();
|
||||
const [voted, setVoted] = useState<boolean | null>(null);
|
||||
const [showReasonInput, setShowReasonInput] = useState(false);
|
||||
const [reason, setReason] = useState('');
|
||||
|
||||
const handleVote = (useful: boolean) => {
|
||||
setVoted(useful);
|
||||
if (!useful) {
|
||||
setShowReasonInput(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setVoted(true);
|
||||
mixpanelClient.track('helpfulness_vote', {
|
||||
path: pathname,
|
||||
useful: useful,
|
||||
useful: true,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmitNegativeFeedback = (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!reason.trim()) return;
|
||||
|
||||
setVoted(false);
|
||||
setShowReasonInput(false);
|
||||
|
||||
mixpanelClient.track('helpfulness_vote', {
|
||||
path: pathname,
|
||||
useful: false,
|
||||
reason: reason.trim(),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -28,6 +51,57 @@ export function Feedback() {
|
||||
);
|
||||
}
|
||||
|
||||
if (showReasonInput) {
|
||||
return (
|
||||
<div className="flex flex-col gap-3 max-w-md pt-8 mt-8 border-t">
|
||||
<label
|
||||
htmlFor="feedback-reason"
|
||||
className="text-sm font-medium text-fd-foreground"
|
||||
>
|
||||
How can we improve this page?
|
||||
</label>
|
||||
<form onSubmit={handleSubmitNegativeFeedback} className="flex flex-col gap-2">
|
||||
<textarea
|
||||
id="feedback-reason"
|
||||
value={reason}
|
||||
onChange={(e) => setReason(e.target.value)}
|
||||
placeholder="What was missing or confusing?"
|
||||
required
|
||||
maxLength={MAX_CHARS}
|
||||
className="w-full p-2 text-sm bg-transparent border rounded-md resize-y border-fd-border text-fd-foreground focus:outline-none focus:ring-2 focus:ring-fd-accent min-h-[80px]"
|
||||
/>
|
||||
<div className="flex items-center justify-between mt-1">
|
||||
<span className={cn(
|
||||
"text-xs",
|
||||
reason.length >= MAX_CHARS ? "text-red-500 font-medium" : "text-fd-muted-foreground"
|
||||
)}>
|
||||
{reason.length} / {MAX_CHARS}
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setShowReasonInput(false);
|
||||
setReason('');
|
||||
}}
|
||||
className="px-4 py-2 text-sm font-medium transition-colors border rounded-md border-fd-border hover:bg-fd-accent/10"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!reason.trim()}
|
||||
className="px-4 py-2 text-sm font-medium transition-colors rounded-md bg-fd-accent text-fd-accent-foreground disabled:opacity-50 hover:opacity-90"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 border-t pt-8 mt-8">
|
||||
<p className="text-sm text-fd-muted-foreground">Was this page helpful?</p>
|
||||
@@ -53,4 +127,4 @@ export function Feedback() {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user