Skip to content

Commit 6f9a5db

Browse files
committed
feat(web): notification-system
1 parent f6c2582 commit 6f9a5db

File tree

5 files changed

+347
-7
lines changed

5 files changed

+347
-7
lines changed

web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"@kleros/ui-components-library": "^2.6.1",
7171
"@sentry/react": "^7.55.2",
7272
"@sentry/tracing": "^7.55.2",
73+
"@supabase/supabase-js": "^2.33.1",
7374
"@tanstack/react-query": "^4.28.0",
7475
"@types/react-modal": "^3.16.0",
7576
"@web3modal/ethereum": "^2.7.1",

web/src/layout/Header/navbar/Menu/Settings/SendMeNotifications/FormNotifs/FormEmail.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { Dispatch, SetStateAction, useEffect, useMemo } from "react";
1+
import React, { useState, Dispatch, SetStateAction, useMemo, useEffect } from "react";
22
import styled from "styled-components";
3+
34
import { Field } from "@kleros/ui-components-library";
45

56
const StyledField = styled(Field)`

web/src/layout/Header/navbar/Menu/Settings/SendMeNotifications/FormNotifs/index.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import React, { useState } from "react";
22
import styled from "styled-components";
3+
import { useWalletClient, useAccount } from "wagmi";
4+
import { toast } from "react-toastify";
35
import { Checkbox, Button } from "@kleros/ui-components-library";
6+
import { OPTIONS as toastOptions } from "utils/wrapWithToast";
7+
import { uploadSettingsToSupabase } from "utils/uploadSettingsToSupabase";
48
import FormEmail from "./FormEmail";
59

6-
const FormContainer = styled.div`
10+
const FormContainer = styled.form`
711
position: relative;
812
display: flex;
913
flex-direction: column;
@@ -31,15 +35,36 @@ const FormNotifs: React.FC = () => {
3135
const [checkboxStates, setCheckboxStates] = useState<boolean[]>(new Array(OPTIONS.length).fill(false));
3236
const [emailInput, setEmailInput] = useState<string>("");
3337
const [emailIsValid, setEmailIsValid] = useState<boolean>(false);
38+
const { data: walletClient } = useWalletClient();
39+
const { address } = useAccount();
3440

3541
const handleCheckboxChange = (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
3642
const newCheckboxStates = [...checkboxStates];
3743
newCheckboxStates[index] = e.target.checked;
3844
setCheckboxStates(newCheckboxStates);
3945
};
4046

47+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
48+
e.preventDefault();
49+
const tx = await walletClient?.signMessage({
50+
account: address,
51+
message: emailInput,
52+
});
53+
const data = {
54+
body: {
55+
email: emailInput,
56+
address,
57+
signature: tx,
58+
},
59+
};
60+
toast.info("Updating notification settings", toastOptions);
61+
await uploadSettingsToSupabase(data, {});
62+
toast.success("Update is successful", toastOptions);
63+
console.log("🚀 ~ file: index.tsx:123 ~ handleSubmit ~ tx:", tx);
64+
};
65+
4166
return (
42-
<FormContainer>
67+
<FormContainer onSubmit={handleSubmit}>
4368
{OPTIONS.map(({ label }, index) => (
4469
<StyledCheckbox
4570
key={label}
@@ -59,8 +84,7 @@ const FormNotifs: React.FC = () => {
5984
</FormEmailContainer>
6085

6186
<ButtonContainer>
62-
<Button text="Coming Soon!" disabled={true} />
63-
{/* <Button text="Save" disabled={!emailIsValid} /> */}
87+
<Button text="Save" disabled={!emailIsValid} />
6488
</ButtonContainer>
6589
</FormContainer>
6690
);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { verifyMessage } from "viem";
2+
import { createClient } from "@supabase/supabase-js";
3+
4+
const SUPABASE_KEY = process.env.SUPABASE_CLIENT_API_KEY;
5+
const SUPABASE_URL = process.env.SUPABASE_URL;
6+
const supabase = createClient(SUPABASE_URL!, SUPABASE_KEY!);
7+
8+
export const uploadSettingsToSupabase = async function (event: any, context: any) {
9+
try {
10+
// Assuming the event.body contains the data we need
11+
const { email, signature, address } = event.body;
12+
console.log("🚀 ~ file: index.tsx:42 ~ handleSupabase ~ email:", email, signature, address);
13+
14+
// Recover the address from the signature
15+
const recoveredAddress = await verifyMessage({
16+
address,
17+
message: email,
18+
signature,
19+
});
20+
console.log("🚀 ~ file: index.tsx:45 ~ handleSupabase ~ recoveredAddress:", recoveredAddress);
21+
22+
// If the recovered address does not match the provided address, return an error
23+
if (!recoveredAddress) {
24+
throw new Error("Signature verification failed");
25+
}
26+
27+
// Allowed columns to update
28+
const allowedColumns = ["discord", "telegram", "twitter", "matrix", "push", "email"];
29+
30+
console.log("1");
31+
32+
// If the message is empty, delete the user record
33+
if (email === "{}") {
34+
let { data, error } = await supabase.from("users").delete().match({ address: recoveredAddress });
35+
36+
if (error) throw error;
37+
38+
return {
39+
statusCode: 200,
40+
body: JSON.stringify({ message: "Record deleted successfully." }),
41+
};
42+
}
43+
44+
// Parse the signed message
45+
console.log("2", email);
46+
47+
const parsedMessage = JSON.parse(JSON.stringify(email));
48+
console.log("🚀 ~ file: index.tsx:69 ~ handleSupabase ~ parsedMessage:", parsedMessage);
49+
50+
// Prepare the record data based on the allowed columns
51+
let recordData: { [key: string]: any } = {};
52+
for (const key in parsedMessage) {
53+
if (allowedColumns.includes(key)) {
54+
recordData[key] = parsedMessage[key];
55+
}
56+
}
57+
58+
// Assuming you have a 'users' table with 'address' and allowedColumns fields
59+
let { data, error } = await supabase
60+
.from("user-settings")
61+
.upsert({ address, email: email })
62+
.match({ address: address });
63+
64+
console.log("🚀 ~ file: index.tsx:89 ~ handleSupabase ~ data:", data);
65+
if (error) throw error;
66+
67+
return {
68+
statusCode: 200,
69+
body: JSON.stringify({ message: "Record updated successfully." }),
70+
};
71+
} catch (err) {
72+
return {
73+
statusCode: 500,
74+
body: JSON.stringify({ message: `Error: ` }),
75+
};
76+
}
77+
};

0 commit comments

Comments
 (0)