Preferences
This will guide you through integration steps of preferences in react application
1. Integrate SuprSendProvider
Integrate SuprSendProvider as it is needed for creating SuprSend Client and authenticating user.
2. Accessing preferences methods using useSuprSendClient hook
Call useSuprSendClient hook in your react component code to get SuprSend client instance which has all preferences methods.
3. Integrating Preferences
Please refer these sections to understand and implement preferences methods in your react application, as integration steps are same for both the web-sdk and react-sdk.
Example
import { useState, useEffect } from "react";
import Switch from "react-switch";
import {
SuprSendProvider,
ChannelLevelPreferenceOptions,
PreferenceOptions,
useSuprSendClient,
useAuthenticateUser,
} from "@suprsend/react";
// -------------- Category Level Preferences -------------- //
const handleCategoryPreferenceChange = async ({
data,
subcategory,
setPreferenceData,
suprSendClient,
}) => {
const resp = await suprSendClient.user.preferences.updateCategoryPreference(
subcategory.category,
data ? PreferenceOptions.OPT_IN : PreferenceOptions.OPT_OUT
);
if (resp.status === "error") {
console.log(resp.error.message);
} else {
setPreferenceData({ ...resp.body });
}
};
const handleChannelPreferenceInCategoryChange = async ({
channel,
subcategory,
setPreferenceData,
suprSendClient,
}) => {
if (!channel.is_editable) return;
const resp =
await suprSendClient.user.preferences.updateChannelPreferenceInCategory(
channel.channel,
channel.preference === PreferenceOptions.OPT_IN
? PreferenceOptions.OPT_OUT
: PreferenceOptions.OPT_IN,
subcategory.category
);
if (resp.status === "error") {
console.log(resp.error.message);
} else {
setPreferenceData({ ...resp.body });
}
};
function NotificationCategoryPreferences({
preferenceData,
setPreferenceData,
}) {
const suprSendClient = useSuprSendClient();
if (!preferenceData.sections) {
return null;
}
return preferenceData.sections?.map((section, index) => {
return (
<div style={{ marginBottom: 24 }} key={index}>
{section?.name && (
<div
style={{
backgroundColor: "#FAFBFB",
paddingTop: 12,
paddingBottom: 12,
marginBottom: 18,
}}
>
<p
style={{
fontSize: 18,
fontWeight: 500,
color: "#3D3D3D",
}}
>
{section.name}
</p>
<p style={{ color: "#6C727F" }}>{section.description}</p>
</div>
)}
{section?.subcategories?.map((subcategory, index) => {
return (
<div
key={index}
style={{
borderBottom: "1px solid #D9D9D9",
paddingBottom: 12,
marginTop: 18,
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>
<p
style={{
fontSize: 16,
fontWeight: 600,
color: "#3D3D3D",
}}
>
{subcategory.name}
</p>
<p style={{ color: "#6C727F", fontSize: 14 }}>
{subcategory.description}
</p>
</div>
<Switch
disabled={!subcategory.is_editable}
onChange={(data) => {
handleCategoryPreferenceChange({
data,
subcategory,
setPreferenceData,
suprSendClient,
});
}}
uncheckedIcon={false}
checkedIcon={false}
height={20}
width={40}
onColor="#2563EB"
checked={subcategory.preference === PreferenceOptions.OPT_IN}
/>
</div>
<div style={{ display: "flex", gap: 10, marginTop: 12 }}>
{subcategory?.channels.map((channel, index) => {
return (
<Checkbox
key={index}
value={channel.preference}
title={channel.channel}
disabled={!channel.is_editable}
onClick={() => {
handleChannelPreferenceInCategoryChange({
channel,
subcategory,
setPreferenceData,
suprSendClient,
});
}}
/>
);
})}
</div>
</div>
);
})}
</div>
);
});
}
// -------------- Channel Level Preferences -------------- //
const handleOverallChannelPreferenceChange = async ({
channel,
status,
setPreferenceData,
suprSendClient,
}) => {
const resp =
await suprSendClient.user.preferences.updateOverallChannelPreference(
channel.channel,
status
);
if (resp.status === "error") {
console.log(resp.error.message);
} else {
setPreferenceData({ ...resp.body });
}
};
function ChannelLevelPreferernceItem({ channel, setPreferenceData }) {
const suprSendClient = useSuprSendClient();
const [isActive, setIsActive] = useState(false);
return (
<div
style={{
border: "1px solid #D9D9D9",
borderRadius: 5,
padding: "12px 24px",
marginBottom: 24,
}}
>
<div
style={{
cursor: "pointer",
}}
onClick={() => setIsActive(!isActive)}
>
<p
style={{
fontSize: 18,
fontWeight: 500,
color: "#3D3D3D",
}}
>
{channel.channel}
</p>
<p style={{ color: "#6C727F", fontSize: 14 }}>
{channel.is_restricted
? "Allow required notifications only"
: "Allow all notifications"}
</p>
</div>
{isActive && (
<div style={{ marginTop: 12, marginLeft: 24 }}>
<p
style={{
color: "#3D3D3D",
fontSize: 16,
fontWeight: 500,
marginTop: 12,
borderBottom: "1px solid #E8E8E8",
}}
>
{channel.channel} Preferences
</p>
<div style={{ marginTop: 12 }}>
<div style={{ marginBottom: 8 }}>
<div
style={{
display: "flex",
alignItems: "center",
}}
>
<div>
<input
type="radio"
name={`all- ${channel.channel}`}
value={true}
id={`all- ${channel.channel}`}
checked={!channel.is_restricted}
onChange={() => {
handleOverallChannelPreferenceChange({
channel,
status: ChannelLevelPreferenceOptions.ALL,
setPreferenceData,
suprSendClient,
});
}}
/>
</div>
<label
htmlFor={`all- ${channel.channel}`}
style={{ marginLeft: 12 }}
>
All
</label>
</div>
<p style={{ color: "#6C727F", fontSize: 14, marginLeft: 22 }}>
Allow All Notifications, except the ones that I have turned off
</p>
</div>
<div>
<div style={{ display: "flex", alignItems: "center" }}>
<div>
<input
type="radio"
name={`required- ${channel.channel}`}
value={true}
id={`required- ${channel.channel}`}
checked={channel.is_restricted}
onChange={() => {
handleOverallChannelPreferenceChange({
channel,
status: ChannelLevelPreferenceOptions.REQUIRED,
setPreferenceData,
suprSendClient,
});
}}
/>
</div>
<label
htmlFor={`required- ${channel.channel}`}
style={{ marginLeft: 12 }}
>
Required
</label>
</div>
<p style={{ color: "#6C727F", fontSize: 14, marginLeft: 22 }}>
Allow only important notifications related to account and
security settings
</p>
</div>
</div>
</div>
)}
</div>
);
}
function ChannelLevelPreferences({ preferenceData, setPreferenceData }) {
return (
<div>
<div
style={{
backgroundColor: "#FAFBFB",
paddingTop: 12,
paddingBottom: 12,
marginBottom: 18,
}}
>
<p
style={{
fontSize: 18,
fontWeight: 500,
color: "#3D3D3D",
}}
>
What notifications to allow for channel?
</p>
</div>
<div>
{preferenceData.channel_preferences ? (
<div>
{preferenceData.channel_preferences?.map((channel, index) => {
return (
<ChannelLevelPreferernceItem
key={index}
channel={channel}
setPreferenceData={setPreferenceData}
/>
);
})}
</div>
) : (
<p>No Data</p>
)}
</div>
</div>
);
}
// -------------- Main component -------------- //
export default function App() {
return (
<SuprSendProvider
publicApiKey="YOUR_PUBLIC_API_KEY"
distinctId={"YOUR_DISTINCT_ID"}
>
<Preferences />
</SuprSendProvider>
);
}
function Preferences() {
const suprSendClient = useSuprSendClient();
const { authenticatedUser } = useAuthenticateUser();
const [preferenceData, setPreferenceData] = useState();
useEffect(() => {
if (!authenticatedUser) return;
suprSendClient.user.preferences.getPreferences().then((resp) => {
if (resp.status === "error") {
console.log(resp.error.message);
} else {
setPreferenceData({ ...resp.body });
}
});
// listen for update in preferences data
suprSendClient.emitter.on("preferences_updated", (preferenceData) => {
setPreferenceData({ ...preferenceData.body });
});
// listen for errors
suprSendClient.emitter.on("preferences_error", (response) => {
console.log("ERROR:", response?.error?.message);
});
}, [authenticatedUser]);
if (!preferenceData) return <p>Loading...</p>;
return (
<div style={{ margin: 24 }}>
<h3 style={{ marginBottom: 24 }}>Notification Preferences</h3>
<NotificationCategoryPreferences
preferenceData={preferenceData}
setPreferenceData={setPreferenceData}
/>
<ChannelLevelPreferences
preferenceData={preferenceData}
setPreferenceData={setPreferenceData}
/>
</div>
);
}
// -------------- Custom Checkbox Component -------------- //
function Checkbox({ title, value, onClick, disabled }) {
const selected = value === PreferenceOptions.OPT_IN;
return (
<div
style={{
border: "0.5px solid #B5B5B5",
display: "inline-flex",
padding: "0px 20px 0px 4px",
borderRadius: 30,
cursor: disabled ? "not-allowed" : "pointer",
}}
onClick={onClick}
>
<Circle selected={selected} disabled={disabled} />
<p
style={{
marginLeft: 8,
color: "#6C727F",
marginTop: 1,
fontWeight: 500,
paddingBottom: 4,
}}
>
{title}
</p>
</div>
);
}
function Circle({ selected, disabled }) {
const bgColor = selected
? disabled
? "#BDCFF8"
: "#2463EB"
: disabled
? "#D0CFCF"
: "#FFF";
return (
<div
style={{
height: 20,
width: 20,
borderRadius: 100,
border: "0.5px solid #A09F9F",
backgroundColor: bgColor,
marginTop: 3.6,
}}
/>
);
}
Updated 29 days ago