Skip to content

Commit 63caa9a

Browse files
authored
Merge pull request #300 from dagstuan/addWatchAuto
Automatically add watch.
2 parents 0d552cd + ef0f32b commit 63caa9a

21 files changed

+483
-60
lines changed

SkredvarselGarminWeb/SkredvarselGarminWeb/Configuration/AuthenticationConfiguration.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ public static void SetupAuthentication(
2525
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
2626
})
2727
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options
28-
=> options.ExpireTimeSpan = TimeSpan.FromMinutes(60))
28+
=>
29+
{
30+
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
31+
})
2932
.AddScheme<GarminAuthenticationSchemeOptions, GarminAuthenticationHandler>("Garmin", options => { })
3033
.AddGoogle(options =>
3134
{

SkredvarselGarminWeb/SkredvarselGarminWeb/Endpoints/AuthRouteBuilderExtensions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using Microsoft.AspNetCore.Authentication.Cookies;
66
using Microsoft.AspNetCore.Authentication.Facebook;
77
using Microsoft.AspNetCore.Authentication.Google;
8-
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
98
using Microsoft.AspNetCore.Mvc;
109
using Microsoft.Extensions.Primitives;
1110

SkredvarselGarminWeb/SkredvarselGarminWeb/Endpoints/VippsSubscriptionEndpointsRouteBuilderExtensions.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ private static ClaimsPrincipal GetVippsAgreementPrincipal(string userId, UserInf
7373
public static void MapVippsSubscriptionEndpoints(this IEndpointRouteBuilder app)
7474
{
7575
app.MapGet("/createVippsAgreement", async (
76+
[FromQuery]
77+
string? watchKey,
7678
HttpContext ctx,
7779
IVippsApiClient vippsApiClient,
7880
IUserService userService,
@@ -136,6 +138,7 @@ public static void MapVippsSubscriptionEndpoints(this IEndpointRouteBuilder app)
136138
{
137139
Id = createdAgreement.AgreementId,
138140
CallbackId = callbackId,
141+
WatchKey = watchKey,
139142
Created = dateTimeNowProvider.Now.ToUniversalTime(),
140143
UserId = userId,
141144
Status = AgreementStatus.PENDING,
@@ -163,6 +166,7 @@ public static void MapVippsSubscriptionEndpoints(this IEndpointRouteBuilder app)
163166
IVippsApiClient vippsApiClient,
164167
IVippsAgreementService subscriptionService,
165168
IUserService userService,
169+
IWatchService watchService,
166170
INotificationService notificationService,
167171
IBackgroundJobClient backgroundJobClient,
168172
IDateTimeNowProvider dateTimeNowProvider,
@@ -236,10 +240,24 @@ VippsAgreementStatus.Stopped or
236240
throw new Exception("Failed to associate agreement with user.");
237241
}
238242

243+
if (agreement.WatchKey != null)
244+
{
245+
var watchAddRequest = watchService.GetWatchAddRequest(agreement.WatchKey);
246+
247+
if (watchAddRequest != null)
248+
{
249+
watchService.AddWatch(watchAddRequest, agreement.UserId);
250+
}
251+
else
252+
{
253+
logger.LogWarning("Failed to find watch add request with key {watchKey}.", agreement.WatchKey);
254+
}
255+
}
256+
239257
_ = Task.Run(notificationService.NotifyUserSubscribed);
240258

241259
agreement.SetAsActive();
242-
agreement.RemoveCallbackId();
260+
agreement.RemoveCallbackIdAndWatchKey();
243261

244262
try
245263
{

SkredvarselGarminWeb/SkredvarselGarminWeb/Endpoints/WatchApiRouteBuilderExtensions.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
using Microsoft.AspNetCore.Mvc;
44
using Microsoft.EntityFrameworkCore;
5-
using Microsoft.IdentityModel.Tokens;
65

76
using SkredvarselGarminWeb.Configuration;
87
using SkredvarselGarminWeb.Database;
@@ -112,25 +111,18 @@ public static void MapWatchApiEndpoints(this IEndpointRouteBuilder app)
112111
return watches.Select(w => w.ToEndpointModel());
113112
}).RequireAuthorization();
114113

115-
app.MapPost("/api/watches/{watchAddKey}", (HttpContext ctx, string watchAddKey, SkredvarselDbContext dbContext) =>
114+
app.MapPost("/api/watches/{watchAddKey}", (HttpContext ctx, string watchAddKey, SkredvarselDbContext dbContext, IWatchService watchService) =>
116115
{
117116
var user = dbContext.GetUserOrThrow(ctx.User);
118117

119-
var watchAddRequest = dbContext.WatchAddRequests.FirstOrDefault(r => EF.Functions.ILike(r.Key, watchAddKey));
118+
var watchAddRequest = watchService.GetWatchAddRequest(watchAddKey);
120119

121120
if (watchAddRequest == null)
122121
{
123122
return Results.Problem("Fant ikke noen klokke med den koden.", statusCode: (int)HttpStatusCode.BadRequest);
124123
}
125124

126-
dbContext.Remove(watchAddRequest);
127-
dbContext.Add(new WatchEntityModel
128-
{
129-
Id = watchAddRequest.WatchId,
130-
PartNumber = watchAddRequest.PartNumber,
131-
UserId = user.Id
132-
});
133-
dbContext.SaveChanges();
125+
watchService.AddWatch(watchAddRequest, user.Id);
134126

135127
return Results.Ok();
136128
}).RequireAuthorization();

SkredvarselGarminWeb/SkredvarselGarminWeb/Entities/Agreement.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public class Agreement
99

1010
public required Guid? CallbackId { get; set; }
1111

12+
public required string? WatchKey { get; set; }
13+
1214
public required DateTime Created { get; set; }
1315

1416
public required AgreementStatus Status { get; set; }

SkredvarselGarminWeb/SkredvarselGarminWeb/Entities/Extensions/AgreementExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ public static void SetUserId(this Agreement agreement, string userId)
77
agreement.UserId = userId;
88
}
99

10-
public static void RemoveCallbackId(this Agreement agreement)
10+
public static void RemoveCallbackIdAndWatchKey(this Agreement agreement)
1111
{
1212
agreement.CallbackId = null;
13+
agreement.WatchKey = null;
1314
}
1415

1516
public static void SetAsActive(this Agreement agreement)

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/Components/AccountPage/AccountPage.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@ import {
77
DrawerContent,
88
DrawerOverlay,
99
Heading,
10-
Text,
1110
Link,
11+
Text,
1212
} from "@chakra-ui/react";
13-
import { useNavigate } from "react-router-dom";
13+
import { useEffect } from "react";
14+
import {
15+
Link as RouterLink,
16+
useNavigate,
17+
useSearchParams,
18+
} from "react-router-dom";
19+
import { useNavigateOnClose } from "../../hooks/useNavigateOnClose";
1420
import { useUser } from "../../hooks/useUser";
21+
import { useAddWatch } from "../../hooks/useWatches";
1522
import { PersonalInfo } from "./PersonalInfo";
1623
import { Subscription } from "./Subscription";
1724
import { Watches } from "./Watches";
18-
import { Link as RouterLink } from "react-router-dom";
19-
import { useNavigateOnClose } from "../../hooks/useNavigateOnClose";
20-
import { useEffect } from "react";
2125

2226
export const AccountPage = () => {
2327
const { data: user, isLoading: isLoadingUser } = useUser();
@@ -32,6 +36,25 @@ export const AccountPage = () => {
3236
}
3337
}, [user, isLoadingUser]);
3438

39+
const [searchParams, setSearchParams] = useSearchParams();
40+
const watchKey = searchParams.get("watchKey");
41+
42+
const { mutate: mutateAddWatch, isPending: isAddWatchPending } = useAddWatch(
43+
() => {
44+
searchParams.delete("watchKey");
45+
setSearchParams(searchParams, {
46+
replace: true,
47+
preventScrollReset: true,
48+
});
49+
},
50+
);
51+
52+
useEffect(() => {
53+
if (user && watchKey && !isAddWatchPending) {
54+
mutateAddWatch(watchKey);
55+
}
56+
}, [mutateAddWatch, isAddWatchPending, user, watchKey]);
57+
3558
return (
3659
<Drawer isOpen={!!user && !isClosing} onClose={onClose} size="md">
3760
<DrawerOverlay />

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

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
import {
2+
Box,
3+
Center,
4+
Heading,
5+
Icon,
6+
Link,
27
Modal,
3-
ModalOverlay,
8+
ModalBody,
9+
ModalCloseButton,
410
ModalContent,
511
ModalHeader,
6-
ModalCloseButton,
7-
ModalBody,
12+
ModalOverlay,
813
Text,
914
VStack,
10-
Box,
11-
Icon,
12-
Center,
13-
Heading,
14-
Link,
1515
} from "@chakra-ui/react";
16-
import { Link as RouterLink } from "react-router-dom";
17-
import { VippsButton } from "./Buttons/VippsButton";
18-
import { FacebookButton } from "./Buttons/FacebookButton";
19-
import { GoogleButton } from "./Buttons/GoogleButton";
16+
import { ReactElement } from "react";
2017
import { FaPaperPlane } from "react-icons/fa";
18+
import { Link as RouterLink, useSearchParams } from "react-router-dom";
19+
import { useEmailLogin } from "../hooks/useEmailLogin";
2120
import { useNavigateOnClose } from "../hooks/useNavigateOnClose";
22-
import { useUser } from "../hooks/useUser";
2321
import { useNavigateToAccountIfLoggedIn } from "../hooks/useNavigateToAccountIfLoggedIn";
24-
import { OrDivider } from "./OrDivider";
25-
import { useEmailLogin } from "../hooks/useEmailLogin";
22+
import { useUser } from "../hooks/useUser";
23+
import { FacebookButton } from "./Buttons/FacebookButton";
24+
import { GoogleButton } from "./Buttons/GoogleButton";
25+
import { VippsButton } from "./Buttons/VippsButton";
2626
import { EmailLoginForm } from "./EmailLoginForm/EmailLoginForm";
27-
import { ReactElement } from "react";
27+
import { OrDivider } from "./OrDivider";
2828

2929
type BuySubscriptionModalProps = {
3030
headerText?: string;
@@ -47,9 +47,12 @@ export const BuySubscriptionModal = (props: BuySubscriptionModalProps) => {
4747
),
4848
} = props;
4949

50+
const [searchParams] = useSearchParams();
51+
const watchKey = searchParams.get("watchKey");
52+
5053
const { data: user, isLoading: isLoadingUser } = useUser();
5154

52-
useNavigateToAccountIfLoggedIn(user, isLoadingUser);
55+
useNavigateToAccountIfLoggedIn(user, isLoadingUser, watchKey);
5356

5457
const { isClosing, onClose } = useNavigateOnClose("/");
5558

@@ -60,7 +63,7 @@ export const BuySubscriptionModal = (props: BuySubscriptionModalProps) => {
6063
handleEmailInputChange,
6164
handleSubmit,
6265
isPending,
63-
} = useEmailLogin();
66+
} = useEmailLogin(watchKey);
6467

6568
return (
6669
<Modal isOpen={!isLoadingUser && !isClosing} onClose={onClose} isCentered>
@@ -83,7 +86,10 @@ export const BuySubscriptionModal = (props: BuySubscriptionModalProps) => {
8386
</Box>
8487

8588
<VStack w="100%" alignItems="stretch">
86-
<VippsButton text="Kjøp abonnement med" />
89+
<VippsButton
90+
text="Kjøp abonnement med"
91+
link={`/createVippsAgreement${watchKey ? `?watchKey=${watchKey}` : ""}`}
92+
/>
8793
</VStack>
8894
</VStack>
8995

@@ -104,8 +110,12 @@ export const BuySubscriptionModal = (props: BuySubscriptionModalProps) => {
104110
</Heading>
105111
<VStack gap={5} w="100%" alignItems="stretch">
106112
<VStack gap={2} w="100%" alignItems="stretch">
107-
<GoogleButton link="/google-login?returnUrl=/account" />
108-
<FacebookButton link="/facebook-login?returnUrl=/account" />
113+
<GoogleButton
114+
link={`/google-login?returnUrl=/account${watchKey ? `?watchKey=${watchKey}` : ""}`}
115+
/>
116+
<FacebookButton
117+
link={`/facebook-login?returnUrl=/account${watchKey ? `?watchKey=${watchKey}` : ""}`}
118+
/>
109119
</VStack>
110120

111121
<OrDivider text="Eller" />

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import {
2+
Box,
3+
Icon,
24
Modal,
3-
ModalOverlay,
5+
ModalBody,
6+
ModalCloseButton,
47
ModalContent,
58
ModalHeader,
6-
ModalCloseButton,
7-
ModalBody,
8-
Icon,
9-
Box,
10-
Center,
9+
ModalOverlay,
1110
Text,
1211
VStack,
1312
} from "@chakra-ui/react";
1413
import { useNavigateOnClose } from "../../hooks/useNavigateOnClose";
15-
import { useState } from "react";
1614
import { LoginContent } from "./LoginContent";
1715

1816
import { FaPaperPlane } from "react-icons/fa";
@@ -34,7 +32,7 @@ export const LoginModal = (props: LoginModalProps) => {
3432
handleEmailInputChange,
3533
handleSubmit,
3634
isPending,
37-
} = useEmailLogin();
35+
} = useEmailLogin(null);
3836

3937
return (
4038
<Modal isOpen={!isClosing} onClose={onClose} isCentered>

SkredvarselGarminWeb/SkredvarselGarminWeb/Frontend/src/hooks/useEmailLogin.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
import { useMutation } from "@tanstack/react-query";
12
import { useState } from "react";
23
import { api } from "../api";
3-
import { useMutation } from "@tanstack/react-query";
44

5-
export const sendLoginEmail = async (email: string) =>
6-
api.post(`/email-login-send?email=${email}&returnUrl=/account`);
5+
export const sendLoginEmail = async (config: {
6+
email: string;
7+
watchKey: string | null;
8+
}) =>
9+
api.post(
10+
`/email-login-send?email=${config.email}&returnUrl=/account${config.watchKey ? `?watchKey=${config.watchKey}` : ""}`,
11+
);
712

8-
export const useEmailLogin = () => {
13+
export const useEmailLogin = (watchKey: string | null) => {
914
const [showSentEmail, setShowSentEmail] = useState(false);
1015

1116
const [email, setEmail] = useState<string | undefined>(undefined);
@@ -30,7 +35,7 @@ export const useEmailLogin = () => {
3035
if (!email) {
3136
setError("Du må skrive en e-postadresse.");
3237
} else {
33-
mutate(email);
38+
mutate({ email, watchKey });
3439
}
3540
};
3641

0 commit comments

Comments
 (0)