Skip to content

Commit 46ccdb4

Browse files
authored
Merge pull request #228 from dagstuan/subscribeView
Subscribe view
2 parents b00c549 + 4e1d719 commit 46ccdb4

File tree

9 files changed

+197
-94
lines changed

9 files changed

+197
-94
lines changed

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/Buttons/GoogleButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const GoogleButton = ({ link }: GoogleButtonProps) => {
1111
as="a"
1212
href={link}
1313
rounded={"full"}
14+
borderColor="black"
1415
borderRadius={4}
1516
colorScheme="gray"
1617
variant="outline"

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/Buttons/VippsButton.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ type VippsButtonProps = {
88
} & Pick<ButtonProps, "size">;
99

1010
export const VippsButton = (props: VippsButtonProps) => {
11-
const { text = "Kjøp abonnement med", link = "/createVippsAgreement" } =
12-
props;
11+
const { text = "Fortsett med", link = "/createVippsAgreement" } = props;
1312

1413
return (
1514
<Button

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/BuySubscriptionModal.tsx

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,24 @@ import {
88
Text,
99
VStack,
1010
Box,
11-
AbsoluteCenter,
12-
Divider,
1311
Icon,
14-
HStack,
12+
Button,
13+
FormControl,
14+
FormErrorMessage,
15+
Input,
16+
Center,
17+
Heading,
1518
} from "@chakra-ui/react";
1619
import { VippsButton } from "./Buttons/VippsButton";
1720
import { FacebookButton } from "./Buttons/FacebookButton";
1821
import { GoogleButton } from "./Buttons/GoogleButton";
19-
import { VippsIcon } from "./Icons/VippsIcon";
20-
import { FaApplePay, FaCreditCard, FaGooglePay } from "react-icons/fa";
22+
import { FaPaperPlane } from "react-icons/fa";
2123
import { useNavigateOnClose } from "../hooks/useNavigateOnClose";
2224
import { useUser } from "../hooks/useUser";
2325
import { useNavigateToAccountIfLoggedIn } from "../hooks/useNavigateToAccountIfLoggedIn";
2426
import { OrDivider } from "./OrDivider";
27+
import { useEmailLogin } from "../hooks/useEmailLogin";
28+
import { EmailLoginForm } from "./EmailLoginForm/EmailLoginForm";
2529

2630
export const BuySubscriptionModal = () => {
2731
const { data: user, isLoading: isLoadingUser } = useUser();
@@ -30,35 +34,83 @@ export const BuySubscriptionModal = () => {
3034

3135
const { isClosing, onClose } = useNavigateOnClose("/");
3236

37+
const {
38+
email,
39+
showSentEmail,
40+
error,
41+
handleEmailInputChange,
42+
handleSubmit,
43+
isLoading,
44+
} = useEmailLogin();
45+
3346
return (
3447
<Modal isOpen={!isLoadingUser && !isClosing} onClose={onClose} isCentered>
3548
<ModalOverlay />
36-
<ModalContent alignItems="center">
49+
<ModalContent alignItems="center" overflow="hidden">
3750
<ModalHeader>Kjøp abonnement</ModalHeader>
3851
<ModalCloseButton />
39-
<ModalBody w="100%" pb={9}>
40-
<VStack gap={2} w="100%">
41-
<Text fontSize="md" align="center">
42-
Du må være logget inn for å kjøpe abonnement.
43-
</Text>
52+
<ModalBody w="100%" p={0}>
53+
{!showSentEmail && (
54+
<VStack gap={8} w="100%" alignItems="center">
55+
<VStack gap={5} w="80%" alignItems="center">
56+
<Text fontSize="md" align="center">
57+
Abonnement kan kjøpes direkte med Vipps,
58+
<br />
59+
eller logg inn for andre alternativer.
60+
</Text>
4461

45-
<VStack gap={2} mb={7}>
46-
<Text>Du kan betale med:</Text>
47-
<HStack alignItems="center">
48-
<VippsIcon title="Vipps" w={14} h="100%" />
49-
<Icon title="Kort" as={FaCreditCard} w={6} h="100%" />
50-
<Icon title="Apple Pay" as={FaApplePay} w={9} h="100%" />
51-
<Icon title="Google Pay" as={FaGooglePay} w={9} h="100%" />
52-
</HStack>
53-
</VStack>
62+
<VStack w="100%" alignItems="stretch">
63+
<VippsButton />
64+
</VStack>
65+
</VStack>
5466

55-
<VStack w="100%" maxW="sm" gap={5} alignItems="stretch">
56-
<VippsButton />
57-
<OrDivider text="Eller logg inn for alternativer" />
58-
<GoogleButton link="/google-login?returnUrl=/account" />
59-
<FacebookButton link="/facebook-login?returnUrl=/account" />
67+
<Center w="100%" bg="gray.100" pt={4} pb={6}>
68+
<VStack w="80%" maxW="sm" gap={5} alignItems="stretch">
69+
<Heading
70+
textAlign="center"
71+
as="header"
72+
size="sm"
73+
fontWeight="normal"
74+
>
75+
Logg inn / registrer deg
76+
</Heading>
77+
<VStack gap={5} w="100%" alignItems="stretch">
78+
<VStack gap={2} w="100%" alignItems="stretch">
79+
<GoogleButton link="/google-login?returnUrl=/account" />
80+
<FacebookButton link="/facebook-login?returnUrl=/account" />
81+
</VStack>
82+
83+
<OrDivider text="Eller" />
84+
<VStack w="100%" alignItems="stretch">
85+
<EmailLoginForm
86+
email={email}
87+
handleEmailInputChange={handleEmailInputChange}
88+
handleSubmit={handleSubmit}
89+
error={error}
90+
isLoading={isLoading}
91+
/>
92+
</VStack>
93+
</VStack>
94+
</VStack>
95+
</Center>
96+
</VStack>
97+
)}
98+
{showSentEmail && (
99+
<VStack gap={6} pb={6}>
100+
<Box
101+
display="flex"
102+
alignItems="center"
103+
justifyContent="center"
104+
bg="green.500"
105+
color="white"
106+
borderRadius="50%"
107+
boxSize={28}
108+
>
109+
<Icon w={16} h={16} as={FaPaperPlane} />
110+
</Box>
111+
<Text>Sjekk innboksen din for en innloggingslenke.</Text>
60112
</VStack>
61-
</VStack>
113+
)}
62114
</ModalBody>
63115
</ModalContent>
64116
</Modal>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { FormControl, Input, FormErrorMessage, Button } from "@chakra-ui/react";
2+
3+
type EmailLoginFormProps = {
4+
email: string | undefined;
5+
handleEmailInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
6+
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
7+
error: string | undefined;
8+
isLoading: boolean;
9+
};
10+
11+
export const EmailLoginForm = (props: EmailLoginFormProps) => {
12+
const { email, handleEmailInputChange, handleSubmit, error, isLoading } =
13+
props;
14+
15+
return (
16+
<form onSubmit={handleSubmit}>
17+
<FormControl isInvalid={!!error}>
18+
<Input
19+
type="email"
20+
bg="white"
21+
placeholder="E-post"
22+
value={email}
23+
onChange={handleEmailInputChange}
24+
/>
25+
<FormErrorMessage>{error}</FormErrorMessage>
26+
</FormControl>
27+
<Button
28+
mt={4}
29+
w="100%"
30+
colorScheme="green"
31+
isLoading={isLoading}
32+
type="submit"
33+
>
34+
Send innloggingslenke
35+
</Button>
36+
</form>
37+
);
38+
};

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/LoginModal/LoginContent.tsx

Lines changed: 22 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,28 @@
1-
import {
2-
VStack,
3-
FormControl,
4-
Input,
5-
FormErrorMessage,
6-
Button,
7-
Text,
8-
Center,
9-
Link,
10-
} from "@chakra-ui/react";
1+
import { VStack, Text, Center, Link } from "@chakra-ui/react";
112
import { FacebookButton } from "../Buttons/FacebookButton";
123
import { GoogleButton } from "../Buttons/GoogleButton";
134
import { OrDivider } from "../OrDivider";
14-
import { useState } from "react";
15-
import { useMutation } from "react-query";
16-
import { sendLoginEmail } from "../../hooks/useEmailLogin";
175
import { Link as RouterLink } from "react-router-dom";
6+
import { EmailLoginForm } from "../EmailLoginForm/EmailLoginForm";
187

198
type LoginContentProps = {
209
loginText?: string;
21-
onSentEmail: () => void;
10+
email: string | undefined;
11+
handleEmailInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
12+
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
13+
error: string | undefined;
14+
isLoading: boolean;
2215
};
2316

2417
export const LoginContent = (props: LoginContentProps) => {
25-
const { loginText, onSentEmail } = props;
26-
27-
const [email, setEmail] = useState<string | undefined>(undefined);
28-
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
29-
const value = e.target.value;
30-
if (value !== undefined && value !== null) {
31-
setEmail(value);
32-
}
33-
};
34-
const [error, setError] = useState<string | undefined>();
35-
36-
const { mutate, isLoading } = useMutation(sendLoginEmail, {
37-
onSuccess: () => {
38-
onSentEmail();
39-
},
40-
});
41-
42-
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
43-
e.preventDefault();
44-
45-
if (!email) {
46-
setError("Du må skrive en e-postadresse.");
47-
} else {
48-
mutate(email);
49-
}
50-
};
18+
const {
19+
loginText,
20+
email,
21+
handleEmailInputChange,
22+
handleSubmit,
23+
error,
24+
isLoading,
25+
} = props;
5126

5227
return (
5328
<VStack gap={7} alignItems="stretch">
@@ -62,27 +37,13 @@ export const LoginContent = (props: LoginContentProps) => {
6237
<FacebookButton link="/facebook-login?returnUrl=/account" />
6338
</VStack>
6439
<OrDivider text="Eller logg inn med e-post" />
65-
<form onSubmit={handleSubmit}>
66-
<FormControl isInvalid={!!error}>
67-
<Input
68-
type="email"
69-
bg="white"
70-
placeholder="E-post"
71-
value={email}
72-
onChange={handleInputChange}
73-
/>
74-
<FormErrorMessage>{error}</FormErrorMessage>
75-
</FormControl>
76-
<Button
77-
mt={4}
78-
w="100%"
79-
colorScheme="green"
80-
isLoading={isLoading}
81-
type="submit"
82-
>
83-
Send innloggingslenke
84-
</Button>
85-
</form>
40+
<EmailLoginForm
41+
email={email}
42+
handleEmailInputChange={handleEmailInputChange}
43+
handleSubmit={handleSubmit}
44+
error={error}
45+
isLoading={isLoading}
46+
/>
8647
<Center>
8748
<Link as={RouterLink} to="/faq#vippslogin">
8849
Hvorfor kan jeg ikke logge inn med Vipps?

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/LoginModal/LoginModal.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useState } from "react";
1616
import { LoginContent } from "./LoginContent";
1717

1818
import { FaPaperPlane } from "react-icons/fa";
19+
import { useEmailLogin } from "../../hooks/useEmailLogin";
1920

2021
type LoginModalProps = {
2122
loginText?: string;
@@ -26,7 +27,14 @@ export const LoginModal = (props: LoginModalProps) => {
2627

2728
const { isClosing, onClose } = useNavigateOnClose("/");
2829

29-
const [showSentEmail, setShowSentEmail] = useState(false);
30+
const {
31+
email,
32+
showSentEmail,
33+
error,
34+
handleEmailInputChange,
35+
handleSubmit,
36+
isLoading,
37+
} = useEmailLogin();
3038

3139
return (
3240
<Modal isOpen={!isClosing} onClose={onClose} isCentered>
@@ -40,7 +48,11 @@ export const LoginModal = (props: LoginModalProps) => {
4048
{!showSentEmail && (
4149
<LoginContent
4250
loginText={loginText}
43-
onSentEmail={() => setShowSentEmail(true)}
51+
email={email}
52+
handleEmailInputChange={handleEmailInputChange}
53+
handleSubmit={handleSubmit}
54+
error={error}
55+
isLoading={isLoading}
4456
/>
4557
)}
4658
{showSentEmail && (

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/OrDivider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AbsoluteCenter, Box, Divider } from "@chakra-ui/react";
1+
import { AbsoluteCenter, Box, Divider, Text } from "@chakra-ui/react";
22

33
type OrDividerProps = {
44
text?: string;
@@ -8,7 +8,7 @@ export const OrDivider = ({ text = "Eller" }: OrDividerProps) => {
88
return (
99
<Box mb={2} mt={2} position="relative" whiteSpace="nowrap">
1010
<Divider />
11-
<AbsoluteCenter bg="white" px="4">
11+
<AbsoluteCenter bg="transparent" px="4">
1212
{text}
1313
</AbsoluteCenter>
1414
</Box>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,44 @@
1+
import { useState } from "react";
12
import { api } from "../api";
3+
import { useMutation } from "react-query";
24

35
export const sendLoginEmail = async (email: string) =>
46
api.post(`/email-login-send?email=${email}&returnUrl=/account`);
7+
8+
export const useEmailLogin = () => {
9+
const [showSentEmail, setShowSentEmail] = useState(false);
10+
11+
const [email, setEmail] = useState<string | undefined>(undefined);
12+
const handleEmailInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
13+
const value = e.target.value;
14+
if (value !== undefined && value !== null) {
15+
setEmail(value);
16+
}
17+
};
18+
const [error, setError] = useState<string | undefined>();
19+
20+
const { mutate, isLoading } = useMutation(sendLoginEmail, {
21+
onSuccess: () => {
22+
setShowSentEmail(true);
23+
},
24+
});
25+
26+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
27+
e.preventDefault();
28+
29+
if (!email) {
30+
setError("Du må skrive en e-postadresse.");
31+
} else {
32+
mutate(email);
33+
}
34+
};
35+
36+
return {
37+
email,
38+
handleEmailInputChange,
39+
error,
40+
isLoading,
41+
handleSubmit,
42+
showSentEmail,
43+
};
44+
};

0 commit comments

Comments
 (0)