Merged in feat/get-profile (pull request #124)
feat(WEB-169, WEB-203, WEB-204): get profile data from API Approved-by: Michael Zetterberg
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
ADOBE_SCRIPT_SRC=""
|
ADOBE_SCRIPT_SRC=""
|
||||||
|
API_BASEURL="https://tstapi.scandichotels.com"
|
||||||
CMS_ACCESS_TOKEN=""
|
CMS_ACCESS_TOKEN=""
|
||||||
CMS_API_KEY=""
|
CMS_API_KEY=""
|
||||||
CMS_ENVIRONMENT="development"
|
CMS_ENVIRONMENT="development"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export default function Default() {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export default function Default() {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import type { ErrorPage } from "@/types/next/error"
|
||||||
|
|
||||||
|
export default function MyPageOverviewError({ error }: ErrorPage) {
|
||||||
|
console.error(error)
|
||||||
|
return <h1>Error happened, overview</h1>
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import styles from "./page.module.css"
|
|||||||
|
|
||||||
import type { LangParams, PageArgs } from "@/types/params"
|
import type { LangParams, PageArgs } from "@/types/params"
|
||||||
|
|
||||||
export default async function MyPage({ params }: PageArgs<LangParams>) {
|
export default async function MyPageOverview({ params }: PageArgs<LangParams>) {
|
||||||
const user = await serverClient().user.get()
|
const user = await serverClient().user.get()
|
||||||
return (
|
return (
|
||||||
<MaxWidth className={styles.blocks} tag="main">
|
<MaxWidth className={styles.blocks} tag="main">
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import { serverClient } from "@/lib/trpc/server"
|
|
||||||
|
|
||||||
import EditProfile from "@/components/MyProfile/Profile/Edit"
|
import EditProfile from "@/components/MyProfile/Profile/Edit"
|
||||||
|
|
||||||
export default async function EditProfileSlot() {
|
export default function EditProfileSlot() {
|
||||||
const user = await serverClient().user.get()
|
return <EditProfile />
|
||||||
return <EditProfile user={user} />
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import type { ErrorPage } from "@/types/next/error"
|
||||||
|
|
||||||
|
export default function ProfileError({ error }: ErrorPage) {
|
||||||
|
console.error(error)
|
||||||
|
return <h1>Error happened, Profile</h1>
|
||||||
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
import { serverClient } from "@/lib/trpc/server"
|
|
||||||
|
|
||||||
import Profile from "@/components/MyProfile/Profile"
|
import Profile from "@/components/MyProfile/Profile"
|
||||||
|
|
||||||
export default async function ProfileInfo() {
|
export default function ProfileInfo() {
|
||||||
const user = await serverClient().user.get()
|
return <Profile />
|
||||||
return <Profile user={user} />
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
auth.ts
24
auth.ts
@@ -18,7 +18,7 @@ const customProvider = {
|
|||||||
authorization: {
|
authorization: {
|
||||||
url: `${env.CURITY_ISSUER_USER}/oauth/v2/authorize`,
|
url: `${env.CURITY_ISSUER_USER}/oauth/v2/authorize`,
|
||||||
params: {
|
params: {
|
||||||
scope: ["openid"],
|
scope: ["openid", "profile"].join(" "),
|
||||||
/**
|
/**
|
||||||
* The `acr_values` param is used to make Curity display the proper login
|
* The `acr_values` param is used to make Curity display the proper login
|
||||||
* page for Scandic. Without the parameter Curity presents some choices
|
* page for Scandic. Without the parameter Curity presents some choices
|
||||||
@@ -53,9 +53,9 @@ export const config = {
|
|||||||
strategy: "jwt",
|
strategy: "jwt",
|
||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async signIn(...args) {
|
async signIn() {
|
||||||
console.log("****** SIGN IN *******")
|
console.log("****** SIGN IN *******")
|
||||||
console.log(args)
|
console.log(arguments)
|
||||||
console.log("****** END - SIGN IN *******")
|
console.log("****** END - SIGN IN *******")
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@@ -68,6 +68,7 @@ export const config = {
|
|||||||
if (session.user) {
|
if (session.user) {
|
||||||
return {
|
return {
|
||||||
...session,
|
...session,
|
||||||
|
token,
|
||||||
user: {
|
user: {
|
||||||
...session.user,
|
...session.user,
|
||||||
id: token.sub,
|
id: token.sub,
|
||||||
@@ -107,22 +108,27 @@ export const config = {
|
|||||||
console.log("****** END - AUTHORIZED *******")
|
console.log("****** END - AUTHORIZED *******")
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
async jwt({ session, token, trigger }) {
|
async jwt({ session, token, trigger, account }) {
|
||||||
console.log("****** JWT *******")
|
console.log("****** JWT *******")
|
||||||
console.log({ session, token, trigger })
|
console.log({ session, token, trigger, account })
|
||||||
console.log("****** END - JWT *******")
|
console.log("****** END - JWT *******")
|
||||||
|
if (account) {
|
||||||
|
return {
|
||||||
|
access_token: account.access_token,
|
||||||
|
}
|
||||||
|
}
|
||||||
return token
|
return token
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
async signIn(...args) {
|
async signIn() {
|
||||||
console.log("#### SIGNIN EVENT ARGS ######")
|
console.log("#### SIGNIN EVENT ARGS ######")
|
||||||
console.log(args)
|
console.log(arguments)
|
||||||
console.log("#### END - SIGNIN EVENT ARGS ######")
|
console.log("#### END - SIGNIN EVENT ARGS ######")
|
||||||
},
|
},
|
||||||
async session(...args) {
|
async session() {
|
||||||
console.log("#### SESSION EVENT ARGS ######")
|
console.log("#### SESSION EVENT ARGS ######")
|
||||||
console.log(args)
|
console.log(arguments)
|
||||||
console.log("#### END - SESSION EVENT ARGS ######")
|
console.log("#### END - SESSION EVENT ARGS ######")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ import Image from "@/components/Image"
|
|||||||
|
|
||||||
import type { User } from "@/types/user"
|
import type { User } from "@/types/user"
|
||||||
|
|
||||||
export default function CopyButton({
|
export default function CopyButton({ membership }: Pick<User, "membership">) {
|
||||||
membershipId,
|
|
||||||
}: Pick<User, "membershipId">) {
|
|
||||||
function handleCopy() {
|
function handleCopy() {
|
||||||
console.log(`COPIED! (${membershipId})`)
|
console.log(`COPIED! (${membership.membershipNumber})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ export default function Friend({ user }: FriendProps) {
|
|||||||
/>
|
/>
|
||||||
<h3 className={styles.name}>{user.name}</h3>
|
<h3 className={styles.name}>{user.name}</h3>
|
||||||
<div className={styles.membershipContainer}>
|
<div className={styles.membershipContainer}>
|
||||||
<p className={styles.membershipId}>{user.membershipId}</p>
|
<p className={styles.membershipId}>
|
||||||
|
{user.membership.membershipNumber}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import Divider from "@/components/TempDesignSystem/Divider"
|
|
||||||
import Image from "@/components/Image"
|
|
||||||
|
|
||||||
import styles from "./points.module.css"
|
|
||||||
|
|
||||||
import type { QualifyingPointsProps } from "@/types/components/myPages/myPage/qualifyingPoints"
|
|
||||||
|
|
||||||
export default function QualifyingPoints({ user }: QualifyingPointsProps) {
|
|
||||||
return (
|
|
||||||
<div className={styles.qualifyingPoints}>
|
|
||||||
<h4 className={styles.title}>Progress</h4>
|
|
||||||
<Divider variant="dotted" />
|
|
||||||
<div className={styles.container}>
|
|
||||||
<div className={styles.points}>
|
|
||||||
<Image
|
|
||||||
alt="Arrow Up Icon"
|
|
||||||
height={24}
|
|
||||||
src="/_static/icons/arrow_upward.svg"
|
|
||||||
width={24}
|
|
||||||
/>
|
|
||||||
<p className={styles.point}>{user.qualifyingPoints}</p>
|
|
||||||
<h5 className={styles.pointTitle}>Qualifying points</h5>
|
|
||||||
</div>
|
|
||||||
<div className={styles.points}>
|
|
||||||
<Image
|
|
||||||
alt="Arrow Up Icon"
|
|
||||||
height={24}
|
|
||||||
src="/_static/icons/arrow_upward.svg"
|
|
||||||
width={24}
|
|
||||||
/>
|
|
||||||
<p className={styles.point}>{user.nights}</p>
|
|
||||||
<h5 className={styles.pointTitle}>Nights</h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
.qualifyingPoints {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--some-grey-color, #000);
|
|
||||||
/* font-family: var(--ff-brandon-text); */
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 0.6%;
|
|
||||||
line-height: 1.7rem;
|
|
||||||
margin: 0 0 0.7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 950px) {
|
|
||||||
.qualifyingPoints {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: grid;
|
|
||||||
gap: 3.8rem;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--some-grey-color, #4f4f4f);
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.points {
|
|
||||||
align-items: center;
|
|
||||||
display: grid;
|
|
||||||
gap: 1rem;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.point {
|
|
||||||
/* font-family: var(--ff-brandon-text); */
|
|
||||||
font-size: 2.7rem;
|
|
||||||
font-weight: 900;
|
|
||||||
line-height: 2.7rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pointTitle {
|
|
||||||
font-family: var(--ff-fira-sans);
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: 0.6%;
|
|
||||||
line-height: 1.4rem;
|
|
||||||
grid-column: 1/-1;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ export default function TotalPoints({ user }: TotalPointsProps) {
|
|||||||
<div>
|
<div>
|
||||||
<Title>Total Points</Title>
|
<Title>Total Points</Title>
|
||||||
<Divider className={styles.divider} variant="dotted" />
|
<Divider className={styles.divider} variant="dotted" />
|
||||||
<p className={styles.points}>{user.points}</p>
|
<p className={styles.points}>{user.membership.currentPoints}</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Image from "@/components/Image"
|
|||||||
|
|
||||||
import styles from "./profile.module.css"
|
import styles from "./profile.module.css"
|
||||||
|
|
||||||
import type { ProfileProps } from "@/types/components/myPages/myProfile/profile"
|
import type { ContainerProps } from "@/types/components/myPages/myProfile/container"
|
||||||
|
|
||||||
const profileStyles = cva(styles.profile)
|
const profileStyles = cva(styles.profile)
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ export default function Container({
|
|||||||
className,
|
className,
|
||||||
user,
|
user,
|
||||||
...props
|
...props
|
||||||
}: ProfileProps) {
|
}: ContainerProps) {
|
||||||
return (
|
return (
|
||||||
<Card className={profileStyles({ className })} {...props}>
|
<Card className={profileStyles({ className })} {...props}>
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useFormStatus } from "react-dom"
|
import { useFormStatus } from "react-dom"
|
||||||
|
import { useWatch } from "react-hook-form"
|
||||||
|
|
||||||
import { _ } from "@/lib/translation"
|
import { _ } from "@/lib/translation"
|
||||||
import { useProfileStore } from "@/stores/edit-profile"
|
import { useProfileStore } from "@/stores/edit-profile"
|
||||||
@@ -22,6 +23,7 @@ import type { EditFormContentProps } from "@/types/components/myPages/myProfile/
|
|||||||
export default function FormContent({ control }: EditFormContentProps) {
|
export default function FormContent({ control }: EditFormContentProps) {
|
||||||
const { pending } = useFormStatus()
|
const { pending } = useFormStatus()
|
||||||
const setIsPending = useProfileStore((store) => store.setIsPending)
|
const setIsPending = useProfileStore((store) => store.setIsPending)
|
||||||
|
const country = useWatch({ name: "address.country" })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsPending(pending)
|
setIsPending(pending)
|
||||||
@@ -30,10 +32,10 @@ export default function FormContent({ control }: EditFormContentProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>SE</Field.Icon>
|
<Field.Icon>{country}</Field.Icon>
|
||||||
<Field.Label htmlFor="country">*{_("Country")}</Field.Label>
|
<Field.Label htmlFor="address.country">*{_("Country")}</Field.Label>
|
||||||
<Field.Content>
|
<Field.Content>
|
||||||
<CountrySelect name="country" />
|
<CountrySelect name="address.country" />
|
||||||
</Field.Content>
|
</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
@@ -72,9 +74,9 @@ export default function FormContent({ control }: EditFormContentProps) {
|
|||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<PhoneIcon />
|
<PhoneIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.Label htmlFor="phone">*{_("Phone")}</Field.Label>
|
<Field.Label htmlFor="phoneNumber">*{_("Phone")}</Field.Label>
|
||||||
<Field.Content>
|
<Field.Content>
|
||||||
<Phone name="phone" />
|
<Phone countrySelectName="address.country" name="phoneNumber" />
|
||||||
</Field.Content>
|
</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
@@ -82,12 +84,14 @@ export default function FormContent({ control }: EditFormContentProps) {
|
|||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.Label htmlFor="street">*{_("Address")}</Field.Label>
|
<Field.Label htmlFor="address.streetAddress">
|
||||||
|
*{_("Address")}
|
||||||
|
</Field.Label>
|
||||||
<Field.Content>
|
<Field.Content>
|
||||||
<Input
|
<Input
|
||||||
aria-label={_("Street")}
|
aria-label={_("Street")}
|
||||||
control={control}
|
control={control}
|
||||||
name="street"
|
name="address.streetAddress"
|
||||||
placeholder={_("Street 123")}
|
placeholder={_("Street 123")}
|
||||||
registerOptions={{ required: true }}
|
registerOptions={{ required: true }}
|
||||||
/>
|
/>
|
||||||
@@ -98,12 +102,12 @@ export default function FormContent({ control }: EditFormContentProps) {
|
|||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.Label htmlFor="city">*{_("City/State")}</Field.Label>
|
<Field.Label htmlFor="address.city">*{_("City/State")}</Field.Label>
|
||||||
<Field.Content>
|
<Field.Content>
|
||||||
<Input
|
<Input
|
||||||
aria-label={_("City")}
|
aria-label={_("City")}
|
||||||
control={control}
|
control={control}
|
||||||
name="city"
|
name="address.city"
|
||||||
placeholder={_("City")}
|
placeholder={_("City")}
|
||||||
registerOptions={{ required: true }}
|
registerOptions={{ required: true }}
|
||||||
/>
|
/>
|
||||||
@@ -114,12 +118,12 @@ export default function FormContent({ control }: EditFormContentProps) {
|
|||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.Label htmlFor="zip">*{_("Zip code")}</Field.Label>
|
<Field.Label htmlFor="address.zipCode">*{_("Zip code")}</Field.Label>
|
||||||
<Field.Content>
|
<Field.Content>
|
||||||
<Input
|
<Input
|
||||||
aria-label={_("Zip code")}
|
aria-label={_("Zip code")}
|
||||||
control={control}
|
control={control}
|
||||||
name="zip"
|
name="address.zipCode"
|
||||||
placeholder={_("Zip code")}
|
placeholder={_("Zip code")}
|
||||||
registerOptions={{ required: true }}
|
registerOptions={{ required: true }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -30,15 +30,7 @@ export default function Form({ user }: EditFormProps) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const form = useForm<EditProfileSchema>({
|
const form = useForm<EditProfileSchema>({
|
||||||
defaultValues: {
|
defaultValues: user,
|
||||||
country: user.country,
|
|
||||||
city: user.address.city,
|
|
||||||
dob: user.dob,
|
|
||||||
email: user.email,
|
|
||||||
phone: user.phone,
|
|
||||||
street: user.address.street,
|
|
||||||
zip: user.address.zipcode,
|
|
||||||
},
|
|
||||||
criteriaMode: "all",
|
criteriaMode: "all",
|
||||||
mode: "onTouched",
|
mode: "onTouched",
|
||||||
resolver: zodResolver(editProfileSchema),
|
resolver: zodResolver(editProfileSchema),
|
||||||
|
|||||||
@@ -4,26 +4,22 @@ import { _ } from "@/lib/translation"
|
|||||||
import { phoneValidator } from "@/utils/phoneValidator"
|
import { phoneValidator } from "@/utils/phoneValidator"
|
||||||
|
|
||||||
export const editProfileSchema = z.object({
|
export const editProfileSchema = z.object({
|
||||||
city: z
|
"address.country": z
|
||||||
.string({ required_error: _("City is required") })
|
|
||||||
.min(1, { message: _("City is required") }),
|
|
||||||
country: z
|
|
||||||
.string({ required_error: _("Country is required") })
|
.string({ required_error: _("Country is required") })
|
||||||
.min(1, { message: _("Country is required") }),
|
.min(1, { message: _("Country is required") }),
|
||||||
|
"address.city": z.string().optional(),
|
||||||
|
"address.streetAddress": z.string().optional(),
|
||||||
|
"address.zipCode": z
|
||||||
|
.string({ required_error: _("Zip code is required") })
|
||||||
|
.min(1, { message: _("Zip code is required") }),
|
||||||
dob: z
|
dob: z
|
||||||
.string({ required_error: _("Date of Birth is required") })
|
.string({ required_error: _("Date of Birth is required") })
|
||||||
.min(1, { message: _("Date of Birth is required") }),
|
.min(1, { message: _("Date of Birth is required") }),
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
phone: phoneValidator(
|
phoneNumber: phoneValidator(
|
||||||
_("Phone is required"),
|
_("Phone is required"),
|
||||||
_("Please enter a valid phone number")
|
_("Please enter a valid phone number")
|
||||||
),
|
),
|
||||||
street: z
|
|
||||||
.string({ required_error: _("Address is required") })
|
|
||||||
.min(1, { message: _("Address is required") }),
|
|
||||||
zip: z
|
|
||||||
.string({ required_error: _("Zip code is required") })
|
|
||||||
.min(1, { message: _("Zip code is required") }),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export type EditProfileSchema = z.infer<typeof editProfileSchema>
|
export type EditProfileSchema = z.infer<typeof editProfileSchema>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
import Container from "../Container"
|
import Container from "../Container"
|
||||||
import Form from "./Form"
|
import Form from "./Form"
|
||||||
|
|
||||||
import type { ProfileProps } from "@/types/components/myPages/myProfile/profile"
|
export default async function EditProfile() {
|
||||||
|
const user = await serverClient().user.get()
|
||||||
export default function EditProfile(props: ProfileProps) {
|
|
||||||
return (
|
return (
|
||||||
<Container {...props}>
|
<Container user={user}>
|
||||||
<Form user={props.user} />
|
<Form user={user} />
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { _ } from "@/lib/translation"
|
import { _ } from "@/lib/translation"
|
||||||
|
import { countries } from "@/components/TempDesignSystem/Form/Country/countries"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CalendarIcon,
|
CalendarIcon,
|
||||||
@@ -11,22 +12,27 @@ import Field from "../Field"
|
|||||||
|
|
||||||
import styles from "./profile.module.css"
|
import styles from "./profile.module.css"
|
||||||
|
|
||||||
import type { ProfileProps } from "@/types/components/myPages/myProfile/profile"
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
export default function Profile(props: ProfileProps) {
|
export default async function Profile() {
|
||||||
|
const user = await serverClient().user.get()
|
||||||
|
const countryName = countries.find(
|
||||||
|
(country) => country.code === user.address.country
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<Container {...props}>
|
<Container user={user}>
|
||||||
<section className={styles.info}>
|
<section className={styles.info}>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>SE</Field.Icon>
|
<Field.Icon>{user.address.country}</Field.Icon>
|
||||||
<Field.TextLabel>{_("Country")}</Field.TextLabel>
|
<Field.TextLabel>{_("Country")}</Field.TextLabel>
|
||||||
<Field.Content>Sweden</Field.Content>
|
<Field.Content>{countryName?.name}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<CalendarIcon />
|
<CalendarIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("Date of Birth")}</Field.TextLabel>
|
<Field.TextLabel>{_("Date of Birth")}</Field.TextLabel>
|
||||||
|
{/* TODO: Get this from user when API team adds it to payload */}
|
||||||
<Field.Content>27/05/1977</Field.Content>
|
<Field.Content>27/05/1977</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
@@ -34,35 +40,36 @@ export default function Profile(props: ProfileProps) {
|
|||||||
<EmailIcon />
|
<EmailIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("Email")}</Field.TextLabel>
|
<Field.TextLabel>{_("Email")}</Field.TextLabel>
|
||||||
<Field.Content>f*********@g****.com</Field.Content>
|
<Field.Content>{user.email}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<PhoneIcon />
|
<PhoneIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("Phone number")}</Field.TextLabel>
|
<Field.TextLabel>{_("Phone number")}</Field.TextLabel>
|
||||||
<Field.Content>+46 ******00</Field.Content>
|
<Field.Content>{user.phoneNumber}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("Address")}</Field.TextLabel>
|
<Field.TextLabel>{_("Address")}</Field.TextLabel>
|
||||||
<Field.Content>T***************</Field.Content>
|
<Field.Content>{user.address.streetAddress || "-"}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("City/State")}</Field.TextLabel>
|
<Field.TextLabel>{_("City/State")}</Field.TextLabel>
|
||||||
<Field.Content>S*******</Field.Content>
|
{/* TODO: Get this from user when API team adds it to payload */}
|
||||||
|
<Field.Content>{user.address.city || "-"}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<Field.Icon>
|
<Field.Icon>
|
||||||
<HouseIcon />
|
<HouseIcon />
|
||||||
</Field.Icon>
|
</Field.Icon>
|
||||||
<Field.TextLabel>{_("Zip code")}</Field.TextLabel>
|
<Field.TextLabel>{_("Zip code")}</Field.TextLabel>
|
||||||
<Field.Content>1****</Field.Content>
|
<Field.Content>{user.address.zipCode}</Field.Content>
|
||||||
</Field>
|
</Field>
|
||||||
</section>
|
</section>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,256 +1,261 @@
|
|||||||
export const countries = [
|
export const countriesMap = {
|
||||||
{ name: "Afghanistan", code: "AF" },
|
Afghanistan: "AF",
|
||||||
{ name: "Albania", code: "AL" },
|
Albania: "AL",
|
||||||
{ name: "Algeria", code: "DZ" },
|
Algeria: "DZ",
|
||||||
{ name: "American Samoa", code: "AS" },
|
"American Samoa": "AS",
|
||||||
{ name: "Andorra", code: "AD" },
|
Andorra: "AD",
|
||||||
{ name: "Angola", code: "AO" },
|
Angola: "AO",
|
||||||
{ name: "Anguilla", code: "AI" },
|
Anguilla: "AI",
|
||||||
{ name: "Antarctica", code: "AQ" },
|
Antarctica: "AQ",
|
||||||
{ name: "Antigua and Barbuda", code: "AG" },
|
"Antigua and Barbuda": "AG",
|
||||||
{ name: "Argentina", code: "AR" },
|
Argentina: "AR",
|
||||||
{ name: "Armenia", code: "AM" },
|
Armenia: "AM",
|
||||||
{ name: "Aruba", code: "AW" },
|
Aruba: "AW",
|
||||||
{ name: "Australia", code: "AU" },
|
Australia: "AU",
|
||||||
{ name: "Austria", code: "AT" },
|
Austria: "AT",
|
||||||
{ name: "Azerbaijan", code: "AZ" },
|
Azerbaijan: "AZ",
|
||||||
{ name: "Bahamas", code: "BS" },
|
Bahamas: "BS",
|
||||||
{ name: "Bahrain", code: "BH" },
|
Bahrain: "BH",
|
||||||
{ name: "Bangladesh", code: "BD" },
|
Bangladesh: "BD",
|
||||||
{ name: "Barbados", code: "BB" },
|
Barbados: "BB",
|
||||||
{ name: "Belarus", code: "BY" },
|
Belarus: "BY",
|
||||||
{ name: "Belgium", code: "BE" },
|
Belgium: "BE",
|
||||||
{ name: "Belize", code: "BZ" },
|
Belize: "BZ",
|
||||||
{ name: "Benin", code: "BJ" },
|
Benin: "BJ",
|
||||||
{ name: "Bermuda", code: "BM" },
|
Bermuda: "BM",
|
||||||
{ name: "Bhutan", code: "BT" },
|
Bhutan: "BT",
|
||||||
{ name: "Bolivia", code: "BO" },
|
Bolivia: "BO",
|
||||||
{ name: "Bonaire", code: "BQ" },
|
Bonaire: "BQ",
|
||||||
{ name: "Bosnia and Herzegovina", code: "BA" },
|
"Bosnia and Herzegovina": "BA",
|
||||||
{ name: "Botswana", code: "BW" },
|
Botswana: "BW",
|
||||||
{ name: "Bouvet Island", code: "BV" },
|
"Bouvet Island": "BV",
|
||||||
{ name: "Brazil", code: "BR" },
|
Brazil: "BR",
|
||||||
{ name: "British Indian Ocean Territory", code: "IO" },
|
"British Indian Ocean Territory": "IO",
|
||||||
{ name: "Brunei Darussalam", code: "BN" },
|
"Brunei Darussalam": "BN",
|
||||||
{ name: "Bulgaria", code: "BG" },
|
Bulgaria: "BG",
|
||||||
{ name: "Burkina Faso", code: "BF" },
|
"Burkina Faso": "BF",
|
||||||
{ name: "Burundi", code: "BI" },
|
Burundi: "BI",
|
||||||
{ name: "Cambodia", code: "KH" },
|
Cambodia: "KH",
|
||||||
{ name: "Cameroon", code: "CM" },
|
Cameroon: "CM",
|
||||||
{ name: "Canada", code: "CA" },
|
Canada: "CA",
|
||||||
{ name: "Cape Verde", code: "CV" },
|
"Cape Verde": "CV",
|
||||||
{ name: "Cayman Islands", code: "KY" },
|
"Cayman Islands": "KY",
|
||||||
{ name: "Central African Republic", code: "CF" },
|
"Central African Republic": "CF",
|
||||||
{ name: "Chad", code: "TD" },
|
Chad: "TD",
|
||||||
{ name: "Chile", code: "CL" },
|
Chile: "CL",
|
||||||
{ name: "China", code: "CN" },
|
China: "CN",
|
||||||
{ name: "Christmas Island", code: "CX" },
|
"Christmas Island": "CX",
|
||||||
{ name: "Cocos (Keeling) Islands", code: "CC" },
|
"Cocos (Keeling) Islands": "CC",
|
||||||
{ name: "Colombia", code: "CO" },
|
Colombia: "CO",
|
||||||
{ name: "Comoros", code: "KM" },
|
Comoros: "KM",
|
||||||
{ name: "Congo", code: "CG" },
|
Congo: "CG",
|
||||||
{ name: "Congo, The Democratic Republic of the", code: "CD" },
|
"Congo, The Democratic Republic of the": "CD",
|
||||||
{ name: "Cook Islands", code: "CK" },
|
"Cook Islands": "CK",
|
||||||
{ name: "Costa Rica", code: "CR" },
|
"Costa Rica": "CR",
|
||||||
{ name: 'Cote D"Ivoire', code: "CI" },
|
'Cote D"Ivoire': "CI",
|
||||||
{ name: "Croatia", code: "HR" },
|
Croatia: "HR",
|
||||||
{ name: "Cuba", code: "CU" },
|
Cuba: "CU",
|
||||||
{ name: "Curacao", code: "CW" },
|
Curacao: "CW",
|
||||||
{ name: "Cyprus", code: "CY" },
|
Cyprus: "CY",
|
||||||
{ name: "Czech Republic", code: "CZ" },
|
"Czech Republic": "CZ",
|
||||||
{ name: "Denmark", code: "DK" },
|
Denmark: "DK",
|
||||||
{ name: "Djibouti", code: "DJ" },
|
Djibouti: "DJ",
|
||||||
{ name: "Dominica", code: "DM" },
|
Dominica: "DM",
|
||||||
{ name: "Dominican Republic", code: "DO" },
|
"Dominican Republic": "DO",
|
||||||
{ name: "Ecuador", code: "EC" },
|
Ecuador: "EC",
|
||||||
{ name: "Egypt", code: "EG" },
|
Egypt: "EG",
|
||||||
{ name: "El Salvador", code: "SV" },
|
"El Salvador": "SV",
|
||||||
{ name: "Equatorial Guinea", code: "GQ" },
|
"Equatorial Guinea": "GQ",
|
||||||
{ name: "Eritrea", code: "ER" },
|
Eritrea: "ER",
|
||||||
{ name: "Estonia", code: "EE" },
|
Estonia: "EE",
|
||||||
{ name: "Eswatini", code: "SZ" },
|
Eswatini: "SZ",
|
||||||
{ name: "Ethiopia", code: "ET" },
|
Ethiopia: "ET",
|
||||||
{ name: "Falkland Islands (Malvinas)", code: "FK" },
|
"Falkland Islands (Malvinas)": "FK",
|
||||||
{ name: "Faroe Islands", code: "FO" },
|
"Faroe Islands": "FO",
|
||||||
{ name: "Fiji", code: "FJ" },
|
Fiji: "FJ",
|
||||||
{ name: "Finland", code: "FI" },
|
Finland: "FI",
|
||||||
{ name: "France", code: "FR" },
|
France: "FR",
|
||||||
{ name: "French Guiana", code: "GF" },
|
"French Guiana": "GF",
|
||||||
{ name: "French Polynesia", code: "PF" },
|
"French Polynesia": "PF",
|
||||||
{ name: "French Southern Territories", code: "TF" },
|
"French Southern Territories": "TF",
|
||||||
{ name: "Gabon", code: "GA" },
|
Gabon: "GA",
|
||||||
{ name: "Gambia", code: "GM" },
|
Gambia: "GM",
|
||||||
{ name: "Georgia", code: "GE" },
|
Georgia: "GE",
|
||||||
{ name: "Germany", code: "DE" },
|
Germany: "DE",
|
||||||
{ name: "Ghana", code: "GH" },
|
Ghana: "GH",
|
||||||
{ name: "Gibraltar", code: "GI" },
|
Gibraltar: "GI",
|
||||||
{ name: "Greece", code: "GR" },
|
Greece: "GR",
|
||||||
{ name: "Greenland", code: "GL" },
|
Greenland: "GL",
|
||||||
{ name: "Grenada", code: "GD" },
|
Grenada: "GD",
|
||||||
{ name: "Guadeloupe", code: "GP" },
|
Guadeloupe: "GP",
|
||||||
{ name: "Guam", code: "GU" },
|
Guam: "GU",
|
||||||
{ name: "Guatemala", code: "GT" },
|
Guatemala: "GT",
|
||||||
{ name: "Guernsey", code: "GG" },
|
Guernsey: "GG",
|
||||||
{ name: "Guinea", code: "GN" },
|
Guinea: "GN",
|
||||||
{ name: "Guinea-Bissau", code: "GW" },
|
"Guinea-Bissau": "GW",
|
||||||
{ name: "Guyana", code: "GY" },
|
Guyana: "GY",
|
||||||
{ name: "Haiti", code: "HT" },
|
Haiti: "HT",
|
||||||
{ name: "Heard Island and Mcdonald Islands", code: "HM" },
|
"Heard Island and Mcdonald Islands": "HM",
|
||||||
{ name: "Holy See (Vatican City State)", code: "VA" },
|
"Holy See (Vatican City State)": "VA",
|
||||||
{ name: "Honduras", code: "HN" },
|
Honduras: "HN",
|
||||||
{ name: "Hong Kong", code: "HK" },
|
"Hong Kong": "HK",
|
||||||
{ name: "Hungary", code: "HU" },
|
Hungary: "HU",
|
||||||
{ name: "Iceland", code: "IS" },
|
Iceland: "IS",
|
||||||
{ name: "India", code: "IN" },
|
India: "IN",
|
||||||
{ name: "Indonesia", code: "ID" },
|
Indonesia: "ID",
|
||||||
{ name: "Iran, Islamic Republic Of", code: "IR" },
|
"Iran, Islamic Republic Of": "IR",
|
||||||
{ name: "Iraq", code: "IQ" },
|
Iraq: "IQ",
|
||||||
{ name: "Ireland", code: "IE" },
|
Ireland: "IE",
|
||||||
{ name: "Isle of Man", code: "IM" },
|
"Isle of Man": "IM",
|
||||||
{ name: "Israel", code: "IL" },
|
Israel: "IL",
|
||||||
{ name: "Italy", code: "IT" },
|
Italy: "IT",
|
||||||
{ name: "Ivory Coast", code: "CI" },
|
"Ivory Coast": "CI",
|
||||||
{ name: "Jamaica", code: "JM" },
|
Jamaica: "JM",
|
||||||
{ name: "Japan", code: "JP" },
|
Japan: "JP",
|
||||||
{ name: "Jersey", code: "JE" },
|
Jersey: "JE",
|
||||||
{ name: "Jordan", code: "JO" },
|
Jordan: "JO",
|
||||||
{ name: "Kazakhstan", code: "KZ" },
|
Kazakhstan: "KZ",
|
||||||
{ name: "Kenya", code: "KE" },
|
Kenya: "KE",
|
||||||
{ name: "Kiribati", code: "KI" },
|
Kiribati: "KI",
|
||||||
{ name: 'Korea, Democratic People"S Republic of', code: "KP" },
|
'Korea, Democratic People"S Republic of': "KP",
|
||||||
{ name: "Korea, Republic of", code: "KR" },
|
"Korea, Republic of": "KR",
|
||||||
{ name: "Kuwait", code: "KW" },
|
Kuwait: "KW",
|
||||||
{ name: "Kyrgyzstan", code: "KG" },
|
Kyrgyzstan: "KG",
|
||||||
{ name: 'Lao People"S Democratic Republic', code: "LA" },
|
'Lao People"S Democratic Republic': "LA",
|
||||||
{ name: "Laos", code: "LA" },
|
Laos: "LA",
|
||||||
{ name: "Latvia", code: "LV" },
|
Latvia: "LV",
|
||||||
{ name: "Lebanon", code: "LB" },
|
Lebanon: "LB",
|
||||||
{ name: "Lesotho", code: "LS" },
|
Lesotho: "LS",
|
||||||
{ name: "Liberia", code: "LR" },
|
Liberia: "LR",
|
||||||
{ name: "Libyan Arab Jamahiriya", code: "LY" },
|
"Libyan Arab Jamahiriya": "LY",
|
||||||
{ name: "Liechtenstein", code: "LI" },
|
Liechtenstein: "LI",
|
||||||
{ name: "Lithuania", code: "LT" },
|
Lithuania: "LT",
|
||||||
{ name: "Luxembourg", code: "LU" },
|
Luxembourg: "LU",
|
||||||
{ name: "Macao", code: "MO" },
|
Macao: "MO",
|
||||||
{ name: "Macedonia, The Former Yugoslav Republic of", code: "MK" },
|
"Macedonia, The Former Yugoslav Republic of": "MK",
|
||||||
{ name: "Madagascar", code: "MG" },
|
Madagascar: "MG",
|
||||||
{ name: "Malawi", code: "MW" },
|
Malawi: "MW",
|
||||||
{ name: "Malaysia", code: "MY" },
|
Malaysia: "MY",
|
||||||
{ name: "Maldives", code: "MV" },
|
Maldives: "MV",
|
||||||
{ name: "Mali", code: "ML" },
|
Mali: "ML",
|
||||||
{ name: "Malta", code: "MT" },
|
Malta: "MT",
|
||||||
{ name: "Marshall Islands", code: "MH" },
|
"Marshall Islands": "MH",
|
||||||
{ name: "Martinique", code: "MQ" },
|
Martinique: "MQ",
|
||||||
{ name: "Mauritania", code: "MR" },
|
Mauritania: "MR",
|
||||||
{ name: "Mauritius", code: "MU" },
|
Mauritius: "MU",
|
||||||
{ name: "Mayotte", code: "YT" },
|
Mayotte: "YT",
|
||||||
{ name: "Mexico", code: "MX" },
|
Mexico: "MX",
|
||||||
{ name: "Micronesia, Federated States of", code: "FM" },
|
"Micronesia, Federated States of": "FM",
|
||||||
{ name: "Moldova, Republic of", code: "MD" },
|
"Moldova, Republic of": "MD",
|
||||||
{ name: "Monaco", code: "MC" },
|
Monaco: "MC",
|
||||||
{ name: "Mongolia", code: "MN" },
|
Mongolia: "MN",
|
||||||
{ name: "Montenegro", code: "ME" },
|
Montenegro: "ME",
|
||||||
{ name: "Montserrat", code: "MS" },
|
Montserrat: "MS",
|
||||||
{ name: "Morocco", code: "MA" },
|
Morocco: "MA",
|
||||||
{ name: "Mozambique", code: "MZ" },
|
Mozambique: "MZ",
|
||||||
{ name: "Myanmar", code: "MM" },
|
Myanmar: "MM",
|
||||||
{ name: "Namibia", code: "NA" },
|
Namibia: "NA",
|
||||||
{ name: "Nauru", code: "NR" },
|
Nauru: "NR",
|
||||||
{ name: "Nepal", code: "NP" },
|
Nepal: "NP",
|
||||||
{ name: "Netherlands", code: "NL" },
|
Netherlands: "NL",
|
||||||
{ name: "Netherlands Antilles", code: "AN" },
|
"Netherlands Antilles": "AN",
|
||||||
{ name: "New Caledonia", code: "NC" },
|
"New Caledonia": "NC",
|
||||||
{ name: "New Zealand", code: "NZ" },
|
"New Zealand": "NZ",
|
||||||
{ name: "Nicaragua", code: "NI" },
|
Nicaragua: "NI",
|
||||||
{ name: "Niger", code: "NE" },
|
Niger: "NE",
|
||||||
{ name: "Nigeria", code: "NG" },
|
Nigeria: "NG",
|
||||||
{ name: "Niue", code: "NU" },
|
Niue: "NU",
|
||||||
{ name: "Norfolk Island", code: "NF" },
|
"Norfolk Island": "NF",
|
||||||
{ name: "Northern Mariana Islands", code: "MP" },
|
"Northern Mariana Islands": "MP",
|
||||||
{ name: "Norway", code: "NO" },
|
Norway: "NO",
|
||||||
{ name: "Oman", code: "OM" },
|
Oman: "OM",
|
||||||
{ name: "Pakistan", code: "PK" },
|
Pakistan: "PK",
|
||||||
{ name: "Palau", code: "PW" },
|
Palau: "PW",
|
||||||
{ name: "Palestinian Territory, Occupied", code: "PS" },
|
"Palestinian Territory, Occupied": "PS",
|
||||||
{ name: "Panama", code: "PA" },
|
Panama: "PA",
|
||||||
{ name: "Papua New Guinea", code: "PG" },
|
"Papua New Guinea": "PG",
|
||||||
{ name: "Paraguay", code: "PY" },
|
Paraguay: "PY",
|
||||||
{ name: "Peru", code: "PE" },
|
Peru: "PE",
|
||||||
{ name: "Philippines", code: "PH" },
|
Philippines: "PH",
|
||||||
{ name: "Pitcairn", code: "PN" },
|
Pitcairn: "PN",
|
||||||
{ name: "Poland", code: "PL" },
|
Poland: "PL",
|
||||||
{ name: "Portugal", code: "PT" },
|
Portugal: "PT",
|
||||||
{ name: "Puerto Rico", code: "PR" },
|
"Puerto Rico": "PR",
|
||||||
{ name: "Qatar", code: "QA" },
|
Qatar: "QA",
|
||||||
{ name: "RWANDA", code: "RW" },
|
RWANDA: "RW",
|
||||||
{ name: "Reunion", code: "RE" },
|
Reunion: "RE",
|
||||||
{ name: "Romania", code: "RO" },
|
Romania: "RO",
|
||||||
{ name: "Russian Federation", code: "RU" },
|
"Russian Federation": "RU",
|
||||||
{ name: "Saint Barthelemy", code: "BL" },
|
"Saint Barthelemy": "BL",
|
||||||
{ name: "Saint Helena", code: "SH" },
|
"Saint Helena": "SH",
|
||||||
{ name: "Saint Kitts and Nevis", code: "KN" },
|
"Saint Kitts and Nevis": "KN",
|
||||||
{ name: "Saint Lucia", code: "LC" },
|
"Saint Lucia": "LC",
|
||||||
{ name: "Saint Martin", code: "MF" },
|
"Saint Martin": "MF",
|
||||||
{ name: "Saint Pierre and Miquelon", code: "PM" },
|
"Saint Pierre and Miquelon": "PM",
|
||||||
{ name: "Saint Vincent and the Grenadines", code: "VC" },
|
"Saint Vincent and the Grenadines": "VC",
|
||||||
{ name: "Samoa", code: "WS" },
|
Samoa: "WS",
|
||||||
{ name: "San Marino", code: "SM" },
|
"San Marino": "SM",
|
||||||
{ name: "Sao Tome and Principe", code: "ST" },
|
"Sao Tome and Principe": "ST",
|
||||||
{ name: "Saudi Arabia", code: "SA" },
|
"Saudi Arabia": "SA",
|
||||||
{ name: "Senegal", code: "SN" },
|
Senegal: "SN",
|
||||||
{ name: "Serbia", code: "RS" },
|
Serbia: "RS",
|
||||||
{ name: "Seychelles", code: "SC" },
|
Seychelles: "SC",
|
||||||
{ name: "Sierra Leone", code: "SL" },
|
"Sierra Leone": "SL",
|
||||||
{ name: "Singapore", code: "SG" },
|
Singapore: "SG",
|
||||||
{ name: "Sint Maarten", code: "SX" },
|
"Sint Maarten": "SX",
|
||||||
{ name: "Slovakia", code: "SK" },
|
Slovakia: "SK",
|
||||||
{ name: "Slovenia", code: "SI" },
|
Slovenia: "SI",
|
||||||
{ name: "Solomon Islands", code: "SB" },
|
"Solomon Islands": "SB",
|
||||||
{ name: "Somalia", code: "SO" },
|
Somalia: "SO",
|
||||||
{ name: "South Africa", code: "ZA" },
|
"South Africa": "ZA",
|
||||||
{ name: "South Georgia and the South Sandwich Islands", code: "GS" },
|
"South Georgia and the South Sandwich Islands": "GS",
|
||||||
{ name: "South Sudan", code: "SS" },
|
"South Sudan": "SS",
|
||||||
{ name: "Spain", code: "ES" },
|
Spain: "ES",
|
||||||
{ name: "Sri Lanka", code: "LK" },
|
"Sri Lanka": "LK",
|
||||||
{ name: "Sudan", code: "SD" },
|
Sudan: "SD",
|
||||||
{ name: "Suriname", code: "SR" },
|
Suriname: "SR",
|
||||||
{ name: "Svalbard and Jan Mayen", code: "SJ" },
|
"Svalbard and Jan Mayen": "SJ",
|
||||||
{ name: "Swaziland", code: "SZ" },
|
Swaziland: "SZ",
|
||||||
{ name: "Sweden", code: "SE" },
|
Sweden: "SE",
|
||||||
{ name: "Switzerland", code: "CH" },
|
Switzerland: "CH",
|
||||||
{ name: "Syrian Arab Republic", code: "SY" },
|
"Syrian Arab Republic": "SY",
|
||||||
{ name: "Taiwan", code: "TW" },
|
Taiwan: "TW",
|
||||||
{ name: "Tajikistan", code: "TJ" },
|
Tajikistan: "TJ",
|
||||||
{ name: "Tanzania, United Republic of", code: "TZ" },
|
"Tanzania, United Republic of": "TZ",
|
||||||
{ name: "Thailand", code: "TH" },
|
Thailand: "TH",
|
||||||
{ name: "Timor-Leste", code: "TL" },
|
"Timor-Leste": "TL",
|
||||||
{ name: "Togo", code: "TG" },
|
Togo: "TG",
|
||||||
{ name: "Tokelau", code: "TK" },
|
Tokelau: "TK",
|
||||||
{ name: "Tonga", code: "TO" },
|
Tonga: "TO",
|
||||||
{ name: "Trinidad and Tobago", code: "TT" },
|
"Trinidad and Tobago": "TT",
|
||||||
{ name: "Tunisia", code: "TN" },
|
Tunisia: "TN",
|
||||||
{ name: "Turkey", code: "TR" },
|
Turkey: "TR",
|
||||||
{ name: "Turkmenistan", code: "TM" },
|
Turkmenistan: "TM",
|
||||||
{ name: "Turks and Caicos Islands", code: "TC" },
|
"Turks and Caicos Islands": "TC",
|
||||||
{ name: "Tuvalu", code: "TV" },
|
Tuvalu: "TV",
|
||||||
{ name: "Uganda", code: "UG" },
|
Uganda: "UG",
|
||||||
{ name: "Ukraine", code: "UA" },
|
Ukraine: "UA",
|
||||||
{ name: "United Arab Emirates", code: "AE" },
|
"United Arab Emirates": "AE",
|
||||||
{ name: "United Kingdom", code: "GB" },
|
"United Kingdom": "GB",
|
||||||
{ name: "United States", code: "US" },
|
"United States": "US",
|
||||||
{ name: "United States Minor Outlying Islands", code: "UM" },
|
"United States Minor Outlying Islands": "UM",
|
||||||
{ name: "Uruguay", code: "UY" },
|
Uruguay: "UY",
|
||||||
{ name: "Uzbekistan", code: "UZ" },
|
Uzbekistan: "UZ",
|
||||||
{ name: "Vanuatu", code: "VU" },
|
Vanuatu: "VU",
|
||||||
{ name: "Venezuela", code: "VE" },
|
Venezuela: "VE",
|
||||||
{ name: "Viet Nam", code: "VN" },
|
"Viet Nam": "VN",
|
||||||
{ name: "Vietnam", code: "VN" },
|
Vietnam: "VN",
|
||||||
{ name: "Virgin Islands, British", code: "VG" },
|
"Virgin Islands, British": "VG",
|
||||||
{ name: "Virgin Islands, U.S.", code: "VI" },
|
"Virgin Islands, U.S.": "VI",
|
||||||
{ name: "Wallis and Futuna", code: "WF" },
|
"Wallis and Futuna": "WF",
|
||||||
{ name: "Western Sahara", code: "EH" },
|
"Western Sahara": "EH",
|
||||||
{ name: "Yemen", code: "YE" },
|
Yemen: "YE",
|
||||||
{ name: "Zambia", code: "ZM" },
|
Zambia: "ZM",
|
||||||
{ name: "Zimbabwe", code: "ZW" },
|
Zimbabwe: "ZW",
|
||||||
{ name: "Åland Islands", code: "AX" },
|
"Åland Islands": "AX",
|
||||||
]
|
} as const
|
||||||
|
|
||||||
|
export const countries = Object.keys(countriesMap).map((country) => ({
|
||||||
|
code: countriesMap[country as keyof typeof countriesMap],
|
||||||
|
name: country as keyof typeof countriesMap,
|
||||||
|
}))
|
||||||
|
|||||||
@@ -35,21 +35,8 @@ export default function CountrySelect({
|
|||||||
name,
|
name,
|
||||||
rules: registerOptions,
|
rules: registerOptions,
|
||||||
})
|
})
|
||||||
const [selectedKey, setSelectedKey] = useState(() => {
|
|
||||||
if (field.value) {
|
|
||||||
const selected = countries.find(
|
|
||||||
(country) =>
|
|
||||||
country.name === field.value || country.code === field.value
|
|
||||||
)
|
|
||||||
if (selected) {
|
|
||||||
return selected.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
})
|
|
||||||
|
|
||||||
function handleChange(country: Key) {
|
function handleChange(country: Key) {
|
||||||
setSelectedKey(String(country))
|
|
||||||
setValue(name, country)
|
setValue(name, country)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +56,7 @@ export default function CountrySelect({
|
|||||||
onBlur={field.onBlur}
|
onBlur={field.onBlur}
|
||||||
onSelectionChange={handleChange}
|
onSelectionChange={handleChange}
|
||||||
ref={field.ref}
|
ref={field.ref}
|
||||||
selectedKey={selectedKey}
|
selectedKey={field.value}
|
||||||
>
|
>
|
||||||
<div className={styles.comboBoxContainer}>
|
<div className={styles.comboBoxContainer}>
|
||||||
<Input
|
<Input
|
||||||
@@ -101,7 +88,7 @@ export default function CountrySelect({
|
|||||||
<ListBoxItem
|
<ListBoxItem
|
||||||
aria-label={country.name}
|
aria-label={country.name}
|
||||||
className={styles.listBoxItem}
|
className={styles.listBoxItem}
|
||||||
id={country.name}
|
id={country.code}
|
||||||
key={`${country.code}-${idx}`}
|
key={`${country.code}-${idx}`}
|
||||||
>
|
>
|
||||||
{country.name}
|
{country.name}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import styles from "./phone.module.css"
|
|||||||
import type { PhoneProps } from "./phone"
|
import type { PhoneProps } from "./phone"
|
||||||
|
|
||||||
export default function Phone({
|
export default function Phone({
|
||||||
name = "phone",
|
countrySelectName = "country",
|
||||||
|
name = "phoneNumber",
|
||||||
placeholder = "",
|
placeholder = "",
|
||||||
registerOptions = {
|
registerOptions = {
|
||||||
required: true,
|
required: true,
|
||||||
@@ -20,11 +21,11 @@ export default function Phone({
|
|||||||
}: PhoneProps) {
|
}: PhoneProps) {
|
||||||
const phoneRef = useRef<PhoneInputRefType>(null)
|
const phoneRef = useRef<PhoneInputRefType>(null)
|
||||||
const { control, formState } = useFormContext()
|
const { control, formState } = useFormContext()
|
||||||
const countryValue = useWatch({ name: "country" })
|
const countryValue = useWatch({ name: countrySelectName })
|
||||||
const defaultCountry = getCountry({
|
const defaultCountry = getCountry({
|
||||||
countries: defaultCountries,
|
countries: defaultCountries,
|
||||||
field: "name",
|
field: "iso2",
|
||||||
value: countryValue,
|
value: String(countryValue).toLowerCase(),
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* Holds the previous selected country to be able to update
|
* Holds the previous selected country to be able to update
|
||||||
@@ -44,13 +45,13 @@ export default function Phone({
|
|||||||
(country: string) => {
|
(country: string) => {
|
||||||
const selectedCountry = getCountry({
|
const selectedCountry = getCountry({
|
||||||
countries: defaultCountries,
|
countries: defaultCountries,
|
||||||
field: "name",
|
field: "iso2",
|
||||||
value: country,
|
value: country.toLowerCase(),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (selectedCountry) {
|
if (selectedCountry) {
|
||||||
phoneRef.current?.setCountry(selectedCountry.iso2)
|
phoneRef.current?.setCountry(selectedCountry.iso2)
|
||||||
prevSelectedCountry.current = country
|
prevSelectedCountry.current = country.toLowerCase()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[phoneRef.current, prevSelectedCountry.current]
|
[phoneRef.current, prevSelectedCountry.current]
|
||||||
@@ -63,8 +64,8 @@ export default function Phone({
|
|||||||
if (prevSelectedCountry.current !== countryValue) {
|
if (prevSelectedCountry.current !== countryValue) {
|
||||||
const selectedCountryPrev = getCountry({
|
const selectedCountryPrev = getCountry({
|
||||||
countries: defaultCountries,
|
countries: defaultCountries,
|
||||||
field: "name",
|
field: "iso2",
|
||||||
value: prevSelectedCountry.current,
|
value: prevSelectedCountry.current.toLowerCase(),
|
||||||
})
|
})
|
||||||
if (
|
if (
|
||||||
field.value.replace("+", "") === selectedCountryPrev?.dialCode
|
field.value.replace("+", "") === selectedCountryPrev?.dialCode
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { RegisterOptions } from "react-hook-form"
|
import type { RegisterOptions } from "react-hook-form"
|
||||||
|
|
||||||
export type PhoneProps = {
|
export type PhoneProps = {
|
||||||
|
countrySelectName?: string
|
||||||
name?: string
|
name?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
registerOptions?: RegisterOptions
|
registerOptions?: RegisterOptions
|
||||||
|
|||||||
2
env/server.ts
vendored
2
env/server.ts
vendored
@@ -10,6 +10,7 @@ export const env = createEnv({
|
|||||||
isServer: typeof window === "undefined" || "Deno" in window,
|
isServer: typeof window === "undefined" || "Deno" in window,
|
||||||
server: {
|
server: {
|
||||||
ADOBE_SCRIPT_SRC: z.string().optional(),
|
ADOBE_SCRIPT_SRC: z.string().optional(),
|
||||||
|
API_BASEURL: z.string(),
|
||||||
BUILD_ID: z.string().default("64rYXBu8o2eHp0Jf"),
|
BUILD_ID: z.string().default("64rYXBu8o2eHp0Jf"),
|
||||||
CMS_ACCESS_TOKEN: z.string(),
|
CMS_ACCESS_TOKEN: z.string(),
|
||||||
CMS_API_KEY: z.string(),
|
CMS_API_KEY: z.string(),
|
||||||
@@ -39,6 +40,7 @@ export const env = createEnv({
|
|||||||
emptyStringAsUndefined: true,
|
emptyStringAsUndefined: true,
|
||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
ADOBE_SCRIPT_SRC: process.env.ADOBE_SCRIPT_SRC,
|
ADOBE_SCRIPT_SRC: process.env.ADOBE_SCRIPT_SRC,
|
||||||
|
API_BASEURL: process.env.API_BASEURL,
|
||||||
BUILD_ID: process.env.BUILD_ID,
|
BUILD_ID: process.env.BUILD_ID,
|
||||||
CMS_ACCESS_TOKEN: process.env.CMS_ACCESS_TOKEN,
|
CMS_ACCESS_TOKEN: process.env.CMS_ACCESS_TOKEN,
|
||||||
CMS_API_KEY: process.env.CMS_API_KEY,
|
CMS_API_KEY: process.env.CMS_API_KEY,
|
||||||
|
|||||||
10
lib/api/endpoints.ts
Normal file
10
lib/api/endpoints.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Nested enum requires namespace
|
||||||
|
*/
|
||||||
|
export namespace endpoints {
|
||||||
|
export const enum v0 {
|
||||||
|
profile = "profile/v0/Profile",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Endpoint = endpoints.v0
|
||||||
60
lib/api/index.ts
Normal file
60
lib/api/index.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import merge from "deepmerge"
|
||||||
|
|
||||||
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
|
import type {
|
||||||
|
RequestOptionsWithJSONBody,
|
||||||
|
RequestOptionsWithOutBody,
|
||||||
|
} from "@/types/fetch"
|
||||||
|
import type { Endpoint } from "./endpoints"
|
||||||
|
|
||||||
|
export { endpoints } from "./endpoints"
|
||||||
|
|
||||||
|
const defaultOptions: RequestInit = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
mode: "cors",
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get(
|
||||||
|
endpoint: Endpoint,
|
||||||
|
options: RequestOptionsWithOutBody
|
||||||
|
) {
|
||||||
|
defaultOptions.method = "GET"
|
||||||
|
return fetch(`${env.API_BASEURL}/${endpoint}`, merge(defaultOptions, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function patch(
|
||||||
|
endpoint: Endpoint,
|
||||||
|
options: RequestOptionsWithJSONBody
|
||||||
|
) {
|
||||||
|
const { body, ...requestOptions } = options
|
||||||
|
defaultOptions.body = JSON.stringify(body)
|
||||||
|
defaultOptions.method = "PATCH"
|
||||||
|
return fetch(
|
||||||
|
`${env.API_BASEURL}/${endpoint}`,
|
||||||
|
merge(defaultOptions, requestOptions)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function post(
|
||||||
|
endpoint: Endpoint,
|
||||||
|
options: RequestOptionsWithJSONBody
|
||||||
|
) {
|
||||||
|
const { body, ...requestOptions } = options
|
||||||
|
defaultOptions.body = JSON.stringify(body)
|
||||||
|
defaultOptions.method = "POST"
|
||||||
|
return fetch(
|
||||||
|
`${env.API_BASEURL}/${endpoint}`,
|
||||||
|
merge(defaultOptions, requestOptions)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function remove(
|
||||||
|
endpoint: Endpoint,
|
||||||
|
options: RequestOptionsWithOutBody
|
||||||
|
) {
|
||||||
|
defaultOptions.method = "DELETE"
|
||||||
|
return fetch(`${env.API_BASEURL}/${endpoint}`, merge(defaultOptions, options))
|
||||||
|
}
|
||||||
@@ -4,11 +4,11 @@ import { useState } from "react"
|
|||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||||
import { httpBatchLink } from "@trpc/client"
|
import { httpBatchLink } from "@trpc/client"
|
||||||
import { env } from "@/env/client"
|
import { env } from "@/env/client"
|
||||||
import { api } from "./client"
|
import { trpc } from "./client"
|
||||||
import { transformer } from "@/server/transformer"
|
import { transformer } from "@/server/transformer"
|
||||||
|
|
||||||
function initializeTrpcClient() {
|
function initializeTrpcClient() {
|
||||||
return api.createClient({
|
return trpc.createClient({
|
||||||
links: [
|
links: [
|
||||||
httpBatchLink({
|
httpBatchLink({
|
||||||
transformer,
|
transformer,
|
||||||
@@ -25,8 +25,8 @@ export default function TrpcProvider({ children }: React.PropsWithChildren) {
|
|||||||
const [queryClient] = useState(() => new QueryClient({}))
|
const [queryClient] = useState(() => new QueryClient({}))
|
||||||
const [trpcClient] = useState(() => initializeTrpcClient())
|
const [trpcClient] = useState(() => initializeTrpcClient())
|
||||||
return (
|
return (
|
||||||
<api.Provider client={trpcClient} queryClient={queryClient}>
|
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
||||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||||
</api.Provider>
|
</trpc.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ import { createTRPCReact } from "@trpc/react-query"
|
|||||||
|
|
||||||
import type { AppRouter } from "@/server"
|
import type { AppRouter } from "@/server"
|
||||||
|
|
||||||
export const api = createTRPCReact<AppRouter>({})
|
export const trpc = createTRPCReact<AppRouter>({})
|
||||||
|
|||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -22,6 +22,7 @@
|
|||||||
"@trpc/server": "^11.0.0-next-beta.318",
|
"@trpc/server": "^11.0.0-next-beta.318",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
"deepmerge": "^4.3.1",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
@@ -4091,6 +4092,14 @@
|
|||||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/deepmerge": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/defer-to-connect": {
|
"node_modules/defer-to-connect": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"@trpc/server": "^11.0.0-next-beta.318",
|
"@trpc/server": "^11.0.0-next-beta.318",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
"deepmerge": "^4.3.1",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
|
|||||||
@@ -11,12 +11,10 @@ export function unauthorizedError() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function internalServerError() {
|
export function forbiddenError() {
|
||||||
return new TRPCError({
|
return new TRPCError({
|
||||||
code: TRPC_ERROR_CODES_BY_NUMBER[
|
code: TRPC_ERROR_CODES_BY_NUMBER[TRPC_ERROR_CODES_BY_KEY.FORBIDDEN],
|
||||||
TRPC_ERROR_CODES_BY_KEY.INTERNAL_SERVER_ERROR
|
message: `You do not have permission!`,
|
||||||
],
|
|
||||||
message: `Internal Server Error!`,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,3 +24,12 @@ export function badRequestError(msg = "Bad request!") {
|
|||||||
message: msg,
|
message: msg,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function internalServerError() {
|
||||||
|
return new TRPCError({
|
||||||
|
code: TRPC_ERROR_CODES_BY_NUMBER[
|
||||||
|
TRPC_ERROR_CODES_BY_KEY.INTERNAL_SERVER_ERROR
|
||||||
|
],
|
||||||
|
message: `Internal Server Error!`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
|
import { countriesMap } from "@/components/TempDesignSystem/Form/Country/countries"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
/**
|
|
||||||
* Return value from jsonplaceholder.com/users/1
|
|
||||||
* Add proper user object expectation when fetching
|
|
||||||
* from Scandic API
|
|
||||||
*/
|
|
||||||
export const getUserSchema = z.object({
|
export const getUserSchema = z.object({
|
||||||
address: z.object({
|
address: z.object({
|
||||||
city: z.string(),
|
city: z.string().optional(),
|
||||||
geo: z.object({}),
|
country: z.nativeEnum(countriesMap),
|
||||||
street: z.string(),
|
streetAddress: z.string().optional(),
|
||||||
suite: z.string(),
|
zipCode: z.string(),
|
||||||
zipcode: z.string(),
|
|
||||||
}),
|
|
||||||
company: z.object({
|
|
||||||
bs: z.string(),
|
|
||||||
catchPhrase: z.string(),
|
|
||||||
name: z.string(),
|
|
||||||
}),
|
}),
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
id: z.number(),
|
gender: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
phone: z.string(),
|
language: z.string(),
|
||||||
username: z.string(),
|
lastName: z.string(),
|
||||||
website: z.string(),
|
membership: z.object({
|
||||||
|
currentPoints: z.number(),
|
||||||
|
expirationDate: z.string(),
|
||||||
|
membershipNumber: z.string(),
|
||||||
|
memberSince: z.string(),
|
||||||
|
}),
|
||||||
|
phoneNumber: z.string(),
|
||||||
|
profileId: z.string(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,112 +1,77 @@
|
|||||||
import { badRequestError, internalServerError } from "@/server/errors/trpc"
|
import * as api from "@/lib/api"
|
||||||
|
import { benefits, extendedUser, nextLevelPerks } from "./temp"
|
||||||
|
import {
|
||||||
|
badRequestError,
|
||||||
|
forbiddenError,
|
||||||
|
internalServerError,
|
||||||
|
unauthorizedError,
|
||||||
|
} from "@/server/errors/trpc"
|
||||||
import { protectedProcedure, router } from "@/server/trpc"
|
import { protectedProcedure, router } from "@/server/trpc"
|
||||||
import { getUserSchema } from "./output"
|
import { getUserSchema } from "./output"
|
||||||
|
|
||||||
import { extendedUser } from "./temp"
|
function fakingRequest<T>(payload: T): Promise<T> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(payload)
|
||||||
|
}, 1500)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const userQueryRouter = router({
|
export const userQueryRouter = router({
|
||||||
get: protectedProcedure.query(async function (opts) {
|
get: protectedProcedure.query(async function ({ ctx }) {
|
||||||
// TODO: Make request to get user data from Scandic API
|
try {
|
||||||
const response = await fetch(
|
const apiResponse = await api.get(api.endpoints.v0.profile, {
|
||||||
"https://jsonplaceholder.typicode.com/users/1",
|
|
||||||
{
|
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!apiResponse.ok) {
|
||||||
|
switch (apiResponse.status) {
|
||||||
|
case 400:
|
||||||
|
throw badRequestError()
|
||||||
|
case 401:
|
||||||
|
throw unauthorizedError()
|
||||||
|
case 403:
|
||||||
|
throw forbiddenError()
|
||||||
|
default:
|
||||||
|
throw internalServerError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
if (!response.ok) {
|
const apiJson = await apiResponse.json()
|
||||||
|
if (!apiJson.data?.length) {
|
||||||
|
throw internalServerError()
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifiedData = getUserSchema.safeParse(apiJson.data[0].attributes)
|
||||||
|
if (!verifiedData.success) {
|
||||||
|
console.info(`Get User - Verified Data Error`)
|
||||||
|
console.error(verifiedData.error)
|
||||||
|
throw badRequestError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...extendedUser,
|
||||||
|
...verifiedData.data,
|
||||||
|
firstName: verifiedData.data.name,
|
||||||
|
name: `${verifiedData.data.name} ${verifiedData.data.lastName}`,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.info(`GEt User Error`)
|
||||||
|
console.error(error)
|
||||||
throw internalServerError()
|
throw internalServerError()
|
||||||
}
|
}
|
||||||
const json = await response.json()
|
|
||||||
const validJson = getUserSchema.safeParse(json)
|
|
||||||
if (!validJson.success) {
|
|
||||||
throw badRequestError()
|
|
||||||
}
|
|
||||||
|
|
||||||
const [firstname, lastname] = validJson.data.name.split(" ")
|
|
||||||
const [phone] = validJson.data.phone.split(" ")
|
|
||||||
return {
|
|
||||||
...validJson.data,
|
|
||||||
firstname,
|
|
||||||
lastname,
|
|
||||||
phone,
|
|
||||||
...extendedUser,
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
benefits: router({
|
benefits: router({
|
||||||
current: protectedProcedure.query(async function (opts) {
|
current: protectedProcedure.query(async function (opts) {
|
||||||
// TODO: Make request to get user data from Scandic API
|
// TODO: Make request to get user data from Scandic API
|
||||||
|
return await fakingRequest<typeof benefits>(benefits)
|
||||||
const currentBenefits = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
value: "€5 voucher",
|
|
||||||
explanation: "to spend in bar & restaurant for each night",
|
|
||||||
subtitle:
|
|
||||||
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
|
||||||
href: "#",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
value: "Breakfast to go",
|
|
||||||
explanation: "for early birds, when staying",
|
|
||||||
subtitle:
|
|
||||||
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
|
||||||
href: "#",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
value: "15% discount",
|
|
||||||
explanation: "in the restaurant & the bar",
|
|
||||||
subtitle:
|
|
||||||
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
|
||||||
href: "#",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const response = currentBenefits
|
|
||||||
return response
|
|
||||||
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw internalServerError()
|
|
||||||
// }
|
|
||||||
// const json = await response.json()
|
|
||||||
// const validJson = getUserSchema.parse(json)
|
|
||||||
// if (!validJson) {
|
|
||||||
// throw badRequestError()
|
|
||||||
// }
|
|
||||||
// return validJson
|
|
||||||
}),
|
}),
|
||||||
nextLevel: protectedProcedure.query(async function (opts) {
|
nextLevel: protectedProcedure.query(async function (opts) {
|
||||||
// TODO: Make request to get user data from Scandic API
|
// TODO: Make request to get user data from Scandic API
|
||||||
|
return await fakingRequest<typeof nextLevelPerks>(nextLevelPerks)
|
||||||
const nextLevelPerks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
|
|
||||||
explanation: "Free soft drink voucher for the kids when staying",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
|
|
||||||
explanation: "Free early check in",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
explanation: "25% extra bonus points on each stay",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const response = { nextLevel: "Close Friend", perks: nextLevelPerks }
|
|
||||||
return response
|
|
||||||
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw internalServerError()
|
|
||||||
// }
|
|
||||||
// const json = await response.json()
|
|
||||||
// const validJson = getUserSchema.parse(json)
|
|
||||||
// if (!validJson) {
|
|
||||||
// throw badRequestError()
|
|
||||||
// }
|
|
||||||
// return validJson
|
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,32 @@
|
|||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
|
export const benefits = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
value: "€5 voucher",
|
||||||
|
explanation: "to spend in bar & restaurant for each night",
|
||||||
|
subtitle:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
||||||
|
href: "#",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
value: "Breakfast to go",
|
||||||
|
explanation: "for early birds, when staying",
|
||||||
|
subtitle:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
||||||
|
href: "#",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
value: "15% discount",
|
||||||
|
explanation: "in the restaurant & the bar",
|
||||||
|
subtitle:
|
||||||
|
"Lorem ipsum dolor sit amet consectetur. Pharetra lectus sagittis turpis blandit feugiat amet enim massa.",
|
||||||
|
href: "#",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
export const challenges = {
|
export const challenges = {
|
||||||
journeys: [
|
journeys: [
|
||||||
{
|
{
|
||||||
@@ -27,6 +54,26 @@ export const challenges = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const nextLevelPerks = {
|
||||||
|
nextLevel: "Close Friend",
|
||||||
|
perks: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
|
||||||
|
explanation: "Free soft drink voucher for the kids when staying",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
|
||||||
|
explanation: "Free early check in",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
explanation: "25% extra bonus points on each stay",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
export const shortcuts = [
|
export const shortcuts = [
|
||||||
{
|
{
|
||||||
href: "#",
|
href: "#",
|
||||||
@@ -88,13 +135,9 @@ export const stays = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export const extendedUser = {
|
export const extendedUser = {
|
||||||
country: "United States",
|
|
||||||
dob: dt("1977-07-05").format("YYYY-MM-DD"),
|
dob: dt("1977-07-05").format("YYYY-MM-DD"),
|
||||||
journeys: challenges.journeys,
|
journeys: challenges.journeys,
|
||||||
membershipId: 30812404844732,
|
|
||||||
nights: 14,
|
nights: 14,
|
||||||
points: 20720,
|
|
||||||
qualifyingPoints: 5000,
|
|
||||||
shortcuts,
|
shortcuts,
|
||||||
stays,
|
stays,
|
||||||
victories: challenges.victories,
|
victories: challenges.victories,
|
||||||
|
|||||||
@@ -14,17 +14,16 @@ export const publicProcedure = t.procedure
|
|||||||
export const protectedProcedure = t.procedure.use(async function (opts) {
|
export const protectedProcedure = t.procedure.use(async function (opts) {
|
||||||
const authRequired = opts.meta?.authRequired ?? true
|
const authRequired = opts.meta?.authRequired ?? true
|
||||||
const session = await opts.ctx.auth()
|
const session = await opts.ctx.auth()
|
||||||
if (authRequired) {
|
|
||||||
if (!session?.user) {
|
if (!authRequired && env.NODE_ENV === "development") {
|
||||||
throw unauthorizedError()
|
console.info(
|
||||||
}
|
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
||||||
} else {
|
)
|
||||||
if (env.NODE_ENV === "development") {
|
console.info(`path: ${opts.path} | type: ${opts.type}`)
|
||||||
console.info(
|
}
|
||||||
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
|
||||||
)
|
if (!session?.user) {
|
||||||
console.info(`path: ${opts.path} | type: ${opts.type}`)
|
throw unauthorizedError()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return opts.next({
|
return opts.next({
|
||||||
|
|||||||
11
types/auth.d.ts
vendored
11
types/auth.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
import "next-auth"
|
import type { JWT } from "next-auth/jwt"
|
||||||
|
|
||||||
// Module augmentation
|
// Module augmentation
|
||||||
// https://authjs.dev/getting-started/typescript#popular-interfaces-to-augment
|
// https://authjs.dev/getting-started/typescript#popular-interfaces-to-augment
|
||||||
@@ -20,10 +20,7 @@ declare module "next-auth" {
|
|||||||
/**
|
/**
|
||||||
* Returned by `useSession`, `auth`, contains information about the active session.
|
* Returned by `useSession`, `auth`, contains information about the active session.
|
||||||
*/
|
*/
|
||||||
interface Session {}
|
interface Session {
|
||||||
}
|
token: JWT
|
||||||
|
}
|
||||||
declare module "next-auth/jwt" {
|
|
||||||
/** Returned by the `jwt` callback and `auth`, when using JWT sessions */
|
|
||||||
interface JWT {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
6
types/components/myPages/myProfile/container.ts
Normal file
6
types/components/myPages/myProfile/container.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import type { CardProps } from "./card/card"
|
||||||
|
import type { User } from "@/types/user"
|
||||||
|
|
||||||
|
export interface ContainerProps extends CardProps {
|
||||||
|
user: User
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { User } from "@/types/user"
|
|
||||||
|
|
||||||
export interface ProfileProps extends React.HTMLAttributes<HTMLElement> {
|
|
||||||
user: User
|
|
||||||
}
|
|
||||||
7
types/fetch.ts
Normal file
7
types/fetch.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export interface RequestOptionsWithJSONBody
|
||||||
|
extends Omit<RequestInit, "body" | "method"> {
|
||||||
|
body: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RequestOptionsWithOutBody
|
||||||
|
extends Omit<RequestInit, "body" | "method"> {}
|
||||||
8
types/jwt.d.ts
vendored
Normal file
8
types/jwt.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Module augmentation
|
||||||
|
// https://authjs.dev/getting-started/typescript#popular-interfaces-to-augment
|
||||||
|
declare module "next-auth/jwt" {
|
||||||
|
/** Returned by the `jwt` callback and `auth`, when using JWT sessions */
|
||||||
|
interface JWT {
|
||||||
|
access_token: string
|
||||||
|
}
|
||||||
|
}
|
||||||
8
types/next/error.ts
Normal file
8
types/next/error.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
interface NextError extends Error {
|
||||||
|
digest?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ErrorPage {
|
||||||
|
error: NextError
|
||||||
|
reset: () => void
|
||||||
|
}
|
||||||
@@ -24,16 +24,15 @@ type Victory = {
|
|||||||
title: string
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All extended field needs to be added by API team to response or
|
||||||
|
* we have to get the values from elsewhere
|
||||||
|
*/
|
||||||
export interface User extends z.infer<typeof getUserSchema> {
|
export interface User extends z.infer<typeof getUserSchema> {
|
||||||
country: string
|
|
||||||
dob: string
|
dob: string
|
||||||
firstname: string
|
firstName: string
|
||||||
journeys: Journey[]
|
journeys: Journey[]
|
||||||
lastname: string
|
|
||||||
membershipId: number
|
|
||||||
nights: number
|
nights: number
|
||||||
points: number
|
|
||||||
qualifyingPoints: number
|
|
||||||
shortcuts: ShortcutLink[]
|
shortcuts: ShortcutLink[]
|
||||||
stays: Stay[]
|
stays: Stay[]
|
||||||
victories: Victory[]
|
victories: Victory[]
|
||||||
|
|||||||
Reference in New Issue
Block a user