-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow editing shipping information in profile settings (#82)
* Add /accounts/get and */update to fetch/update shipping info * Update db schema adding shipping info * Add ShippingInformationForm component and use it on the setting page
- Loading branch information
1 parent
e70cf87
commit a60c997
Showing
10 changed files
with
287 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec" | ||
import { z } from "zod" | ||
import { accountSchema } from "fake-snippets-api/lib/db/schema" | ||
|
||
export default withRouteSpec({ | ||
methods: ["GET"], | ||
auth: "session", | ||
jsonResponse: z.object({ | ||
account: accountSchema, | ||
}), | ||
})(async (req, ctx) => { | ||
const account = ctx.db.getAccount(ctx.auth.account_id) | ||
if (!account) { | ||
return ctx.error(404, { | ||
error_code: "account_not_found", | ||
message: "Account not found", | ||
}) | ||
} | ||
|
||
return ctx.json({ account }) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec" | ||
import { z } from "zod" | ||
import { accountSchema } from "fake-snippets-api/lib/db/schema" | ||
|
||
const shippingInfoSchema = z.object({ | ||
fullName: z.string(), | ||
address: z.string(), | ||
city: z.string(), | ||
state: z.string(), | ||
zipCode: z.string(), | ||
country: z.string(), | ||
}) | ||
|
||
export default withRouteSpec({ | ||
methods: ["POST"], | ||
auth: "session", | ||
jsonBody: z.object({ | ||
shippingInfo: shippingInfoSchema, | ||
}), | ||
jsonResponse: z.object({ | ||
account: accountSchema, | ||
}), | ||
})(async (req, ctx) => { | ||
const { shippingInfo } = req.jsonBody | ||
|
||
const updatedAccount = ctx.db.updateAccount(ctx.auth.account_id, { | ||
shippingInfo, | ||
}) | ||
|
||
if (!updatedAccount) { | ||
return ctx.error(404, { | ||
error_code: "account_not_found", | ||
message: "Account not found", | ||
}) | ||
} | ||
|
||
return ctx.json({ account: updatedAccount }) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import React, { useReducer, useEffect } from "react" | ||
import { Button } from "@/components/ui/button" | ||
import { Input } from "@/components/ui/input" | ||
import { useToast } from "@/hooks/use-toast" | ||
import { useAxios } from "@/hooks/use-axios" | ||
import { useQuery, useMutation, useQueryClient } from "react-query" | ||
import { Loader2 } from "lucide-react" | ||
import { sentenceCase } from "change-case" | ||
|
||
type ShippingInfo = { | ||
fullName: string | ||
address: string | ||
city: string | ||
state: string | ||
zipCode: string | ||
country: string | ||
} | ||
|
||
type Action = | ||
| { type: "SET_FIELD"; field: keyof ShippingInfo; value: string } | ||
| { type: "SET_ALL"; payload: ShippingInfo } | ||
|
||
const initialState: ShippingInfo = { | ||
fullName: "", | ||
address: "", | ||
zipCode: "", | ||
country: "", | ||
city: "", | ||
state: "", | ||
} | ||
|
||
const shippingPlaceholders: ShippingInfo = { | ||
fullName: "Enter your full name", | ||
address: "Enter your street address", | ||
zipCode: "Enter your zip code", | ||
country: "Enter your country", | ||
city: "Enter your city", | ||
state: "Enter your state", | ||
} | ||
|
||
const ShippingInformationForm: React.FC = () => { | ||
const [form, setField] = useReducer( | ||
(state: ShippingInfo, action: Action): ShippingInfo => { | ||
switch (action.type) { | ||
case "SET_FIELD": | ||
return { ...state, [action.field]: action.value } | ||
case "SET_ALL": | ||
return action.payload | ||
default: | ||
return state | ||
} | ||
}, | ||
initialState, | ||
) | ||
const { toast } = useToast() | ||
const axios = useAxios() | ||
const queryClient = useQueryClient() | ||
|
||
const { data: account, isLoading: isLoadingAccount } = useQuery( | ||
"account", | ||
async () => { | ||
const response = await axios.get("/accounts/get") | ||
return response.data.account | ||
}, | ||
) | ||
|
||
const updateShippingMutation = useMutation( | ||
(shippingInfo: ShippingInfo) => | ||
axios.post("/accounts/update", { shippingInfo }), | ||
{ | ||
onSuccess: () => { | ||
queryClient.invalidateQueries("account") | ||
toast({ | ||
title: "Success", | ||
description: "Shipping information updated successfully", | ||
}) | ||
}, | ||
onError: () => { | ||
toast({ | ||
title: "Error", | ||
description: "Failed to update shipping information", | ||
variant: "destructive", | ||
}) | ||
}, | ||
}, | ||
) | ||
|
||
useEffect(() => { | ||
if (account?.shippingInfo) { | ||
setField({ type: "SET_ALL", payload: account.shippingInfo }) | ||
} | ||
}, [account]) | ||
|
||
const handleSubmit = async (e: React.FormEvent) => { | ||
e.preventDefault() | ||
updateShippingMutation.mutate(form) | ||
} | ||
|
||
if (isLoadingAccount) { | ||
return ( | ||
<div className="flex justify-center items-center h-64"> | ||
<Loader2 className="w-8 h-8 animate-spin" /> | ||
</div> | ||
) | ||
} | ||
|
||
const fieldOrder: (keyof ShippingInfo)[] = [ | ||
"fullName", | ||
"address", | ||
"zipCode", | ||
"country", | ||
"city", | ||
"state", | ||
] | ||
|
||
return ( | ||
<form onSubmit={handleSubmit} className="space-y-4"> | ||
{fieldOrder.map((key) => ( | ||
<div key={key}> | ||
<label | ||
htmlFor={key} | ||
className="block text-sm font-medium text-gray-700" | ||
> | ||
{sentenceCase(key)} | ||
</label> | ||
<Input | ||
id={key} | ||
value={form[key]} | ||
onChange={(e) => | ||
setField({ | ||
type: "SET_FIELD", | ||
field: key, | ||
value: e.target.value, | ||
}) | ||
} | ||
placeholder={shippingPlaceholders[key]} | ||
disabled={updateShippingMutation.isLoading} | ||
/> | ||
</div> | ||
))} | ||
<Button type="submit" disabled={updateShippingMutation.isLoading}> | ||
{updateShippingMutation.isLoading ? ( | ||
<> | ||
<Loader2 className="mr-2 h-4 w-4 animate-spin" /> | ||
Updating... | ||
</> | ||
) : ( | ||
"Update" | ||
)} | ||
</Button> | ||
</form> | ||
) | ||
} | ||
|
||
export default ShippingInformationForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters