Skip to content

Commit a1d4c98

Browse files
committed
feat: integrate backend email submission for hire-me quotes
- Connected quote submission to backend mail endpoint at https://thebackend.rocket-champ.pw/mail - Added submitSuccess state to track successful quote submissions - Display success message after quote is sent confirming receipt and next steps - Updated error message to reflect actual submission failure instead of preparation error - Marked email integration tasks as complete in TODO documentation
1 parent b6a2570 commit a1d4c98

2 files changed

Lines changed: 42 additions & 18 deletions

File tree

app/hire-me/page.tsx

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default function HireMePage() {
3636

3737
const [isSubmitting, setIsSubmitting] = useState(false);
3838
const [submitError, setSubmitError] = useState<string | null>(null);
39+
const [submitSuccess, setSubmitSuccess] = useState(false);
3940

4041
const suggestedBudgetRange = budgetRanges.find((range) => {
4142
const max = range.max ?? Number.POSITIVE_INFINITY;
@@ -50,14 +51,28 @@ export default function HireMePage() {
5051
try {
5152
setIsSubmitting(true);
5253
setSubmitError(null);
54+
setSubmitSuccess(false);
5355

5456
const payload = buildPayload();
55-
// TODO: Wire this payload to a backend/email route.
56-
// For now, we just log it so we can inspect the shape during development.
57-
console.log("Hire Me quote payload", payload);
57+
const response = await fetch("https://thebackend.rocket-champ.pw/mail", {
58+
method: "POST",
59+
headers: {
60+
"Content-Type": "application/json",
61+
},
62+
body: JSON.stringify({
63+
type: "hire-quote",
64+
quote: payload,
65+
}),
66+
});
67+
68+
if (!response.ok) {
69+
throw new Error("Failed to submit quote");
70+
}
71+
72+
setSubmitSuccess(true);
5873
} catch {
5974
setSubmitError(
60-
"Something went wrong while preparing your quote. Please try again in a moment."
75+
"Something went wrong while sending your request. Please try again in a moment."
6176
);
6277
} finally {
6378
setIsSubmitting(false);
@@ -150,13 +165,21 @@ export default function HireMePage() {
150165
)}
151166

152167
{state.currentStep === 6 && (
153-
<ContactStep
154-
contact={state.contact}
155-
isSubmitting={isSubmitting}
156-
error={submitError}
157-
onChangeField={updateContactField}
158-
onSubmit={handleSubmit}
159-
/>
168+
<div className="space-y-3">
169+
{submitSuccess && (
170+
<p className="rounded-md border border-green-500/60 bg-green-500/10 p-3 text-xs text-green-300">
171+
Thanks for your request. I&apos;ll review your answers and get back to you with a
172+
refined proposal.
173+
</p>
174+
)}
175+
<ContactStep
176+
contact={state.contact}
177+
isSubmitting={isSubmitting}
178+
error={submitError}
179+
onChangeField={updateContactField}
180+
onSubmit={handleSubmit}
181+
/>
182+
</div>
160183
)}
161184
</div>
162185
</QuoteStepper>

src/features/hireme/docs/TODO.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,14 @@ Create reusable components under `src/features/hireme/components`:
8080
## 6. Email / Backend Integration
8181
- [ ] Decide on submission strategy:
8282
- [ ] Next.js route handler under `app/api/hire-quote/route.ts`, or
83-
- [ ] External email service (e.g. EmailJS, existing backend if any).
84-
- [ ] Define `QuotePayload` DTO matching the state shape.
85-
- [ ] Implement API route that:
86-
- [ ] Receives JSON payload.
87-
- [ ] Constructs email to YOU using conditional templates (budget mismatch vs aligned).
88-
- [ ] Triggers confirmation email to client (simple version first).
89-
- [ ] Wire `submitQuote` in the client to POST to this API and handle loading/success/error states.
83+
- [x] External backend endpoint (`https://thebackend.rocket-champ.pw/mail`).
84+
- [x] Define `QuotePayload` DTO matching the state shape.
85+
- [x] Implement backend `/mail` route that:
86+
- [x] Receives JSON payload.
87+
- [x] Validates `hire-quote` DTO (types, required fields, agreeToTerms, price > 0).
88+
- [x] Constructs email to YOU using conditional templates (budget mismatch vs aligned).
89+
- [x] Triggers confirmation email to client with styling consistent with the site.
90+
- [x] Wire `submitQuote` in the client to POST to this backend and handle loading/success/error states.
9091
- [ ] Add basic server-side validation and spam protection (honeypot field or rate limiting, if needed).
9192

9293
## 7. Styling & Responsiveness

0 commit comments

Comments
 (0)