Skip to content

Commit 6de7ab8

Browse files
refactor(contact): fix try-catch async logic, memory leaks, and a11y roles
1 parent d382fa8 commit 6de7ab8

1 file changed

Lines changed: 38 additions & 25 deletions

File tree

src/pages/Contact/Contact.tsx

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useContext } from "react";
1+
import { useState, useContext, useEffect } from "react";
22
import {
33
Github,
44
Mail,
@@ -28,6 +28,17 @@ function Contact() {
2828
const { mode } = themeContext;
2929
const isDark = mode === "dark";
3030

31+
// FIX: Correctly handle the auto-dismiss popup timer within an effect lifestyle cleanup pattern
32+
useEffect(() => {
33+
if (!showPopup) return;
34+
35+
const timer = setTimeout(() => {
36+
setShowPopup(false);
37+
}, 5000);
38+
39+
return () => clearTimeout(timer);
40+
}, [showPopup]);
41+
3142
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
3243
const { name, value } = e.target;
3344
setFormData((prev) => ({ ...prev, [name]: value }));
@@ -37,21 +48,17 @@ function Contact() {
3748
e.preventDefault();
3849
setIsSubmitting(true);
3950

40-
// Simulate API pipeline delay (formData can now be passed safely to your API)
41-
await new Promise((resolve) => setTimeout(resolve, 1500));
42-
43-
setIsSubmitting(false);
44-
setShowPopup(true);
45-
46-
// Reset Form fields safely
47-
setFormData({ name: "", email: "", subject: "", message: "" });
48-
49-
// Auto-dismiss success notification
50-
const timer = setTimeout(() => {
51-
setShowPopup(false);
52-
}, 5000);
53-
54-
return () => clearTimeout(timer);
51+
// FIX: Wrapped logic inside a proper try/catch/finally block to ensure states reset safely on network failures
52+
try {
53+
// Simulate API pipeline delay
54+
await new Promise((resolve) => setTimeout(resolve, 1500));
55+
setShowPopup(true);
56+
setFormData({ name: "", email: "", subject: "", message: "" });
57+
} catch (error) {
58+
console.error("Failed to route contact payload data:", error);
59+
} finally {
60+
setIsSubmitting(false);
61+
}
5562
};
5663

5764
return (
@@ -102,7 +109,7 @@ function Contact() {
102109
<div className={`w-10 h-10 rounded-xl flex items-center justify-center border shadow-sm ${
103110
isDark ? "bg-slate-900 border-slate-800" : "bg-white border-purple-100"
104111
}`}>
105-
<img src="/crl-icon.png" alt="Logo" className="w-6 h-6 object-contain" />
112+
<img src="/crl-icon.png" alt="GitHub Tracker Logo" className="w-6 h-6 object-contain" />
106113
</div>
107114
<h3 className="text-xl font-bold tracking-tight bg-gradient-to-r from-purple-500 via-indigo-500 to-blue-500 bg-clip-text text-transparent">
108115
GitHub Tracker
@@ -117,24 +124,30 @@ function Contact() {
117124
</div>
118125
</div>
119126

120-
{/* Minimalist Actionable Communication Badges */}
127+
{/* FIX: Swapped out empty <div> wrapper formats for functional semantic anchor link maps */}
121128
<div className="space-y-3 pt-8 lg:pt-0">
122129
{[
123-
{ label: "Direct Support", detail: "support@githubtracker.com", Icon: Mail },
124-
{ label: "Community Hotline", detail: "(123) 456-7890", Icon: Phone },
125-
{ label: "Open-Source Hub", detail: "github.com/yourorg/track", Icon: Github },
126-
].map(({ label, detail, Icon }) => (
127-
<div key={label} className="flex items-center gap-3 group cursor-pointer">
130+
{ label: "Direct Support", detail: "support@githubtracker.com", href: "mailto:support@githubtracker.com", target: "_self", Icon: Mail },
131+
{ label: "Community Hotline", detail: "(123) 456-7890", href: "tel:+11234567890", target: "_self", Icon: Phone },
132+
{ label: "Open-Source Hub", detail: "github.com/yourorg/track", href: "https://github.com/yourorg/track", target: "_blank", Icon: Github },
133+
].map(({ label, detail, href, target, Icon }) => (
134+
<a
135+
key={label}
136+
href={href}
137+
target={target}
138+
rel={target === "_blank" ? "noopener noreferrer" : undefined}
139+
className="flex items-center gap-3 group outline-none focus-visible:ring-2 focus-visible:ring-purple-500/50 rounded-xl p-1"
140+
>
128141
<div className={`p-2 rounded-lg border transition-colors ${
129142
isDark ? "bg-slate-900/50 border-slate-800 text-slate-400 group-hover:text-purple-400 group-hover:border-purple-500/30" : "bg-white border-slate-200 text-slate-500 group-hover:text-purple-600 group-hover:border-purple-200"
130143
}`}>
131144
<Icon className="w-4 h-4" />
132145
</div>
133-
<div>
146+
<div className="overflow-hidden">
134147
<p className="text-[10px] uppercase font-bold tracking-wider text-slate-400">{label}</p>
135148
<p className={`text-xs font-semibold truncate transition-colors ${isDark ? "text-slate-300 group-hover:text-white" : "text-slate-700 group-hover:text-slate-950"}`}>{detail}</p>
136149
</div>
137-
</div>
150+
</a>
138151
))}
139152
</div>
140153
</div>

0 commit comments

Comments
 (0)