import { Box, Button, Card, Checkbox, Chip, CircularProgress, Container, Divider, FormControl, FormHelperText, Input, Option, Select, Typography, } from '@mui/joy' import moment from 'moment' import { useEffect, useState } from 'react' import RealTimeSettings from '../../components/RealTimeSettings' import Logo from '../../Logo' import { useUserProfile } from '../../queries/UserQueries' import { useNotification } from '../../service/NotificationProvider' import { AcceptCircleMemberRequest, CancelSubscription, DeleteCircleMember, GetAllCircleMembers, GetCircleMemberRequests, GetSubscriptionSession, GetUserCircle, JoinCircle, LeaveCircle, PutWebhookURL, UpdateMemberRole, UpdatePassword, } from '../../utils/Fetcher' import { isPlusAccount } from '../../utils/Helpers' import LoadingComponent from '../components/Loading' import ConfirmationModal from '../Modals/Inputs/ConfirmationModal' import PassowrdChangeModal from '../Modals/Inputs/PasswordChangeModal' import APITokenSettings from './APITokenSettings' import MFASettings from './MFASettings' import NotificationSetting from './NotificationSetting' import ProfileSettings from './ProfileSettings' import StorageSettings from './StorageSettings' import ThemeToggle from './ThemeToggle' const Settings = () => { const { data: userProfile } = useUserProfile() const { showNotification } = useNotification() const [userCircles, setUserCircles] = useState([]) const [circleMemberRequests, setCircleMemberRequests] = useState([]) const [circleInviteCode, setCircleInviteCode] = useState('') const [circleMembers, setCircleMembers] = useState([]) const [webhookURL, setWebhookURL] = useState(null) const [webhookError, setWebhookError] = useState(null) const [isAdmin, setIsAdmin] = useState(false) const [changePasswordModal, setChangePasswordModal] = useState(false) const [confirmModalConfig, setConfirmModalConfig] = useState({}) const showConfirmation = ( message, title, onConfirm, confirmText = 'Confirm', cancelText = 'Cancel', color = 'primary', ) => { setConfirmModalConfig({ isOpen: true, message, title, confirmText, cancelText, color, onClose: isConfirmed => { if (isConfirmed) { onConfirm() } setConfirmModalConfig({}) }, }) } useEffect(() => { GetUserCircle().then(resp => { resp.json().then(data => { setUserCircles(data.res ? data.res : []) setWebhookURL(data.res ? data.res[0].webhook_url : null) }) }) GetCircleMemberRequests().then(resp => { resp.json().then(data => { setCircleMemberRequests(data.res ? data.res : []) }) }) GetAllCircleMembers().then(data => { setCircleMembers(data.res ? data.res : []) }) }, []) // useEffect when circleMembers and userprofile: useEffect(() => { if (userProfile && userProfile.id) { const isUserAdmin = circleMembers.some( member => member.userId === userProfile.id && member.role === 'admin', ) setIsAdmin(isUserAdmin) } }, [circleMembers, userProfile]) useEffect(() => { const hash = window.location.hash if (hash) { const sharingSection = document.getElementById( window.location.hash.slice(1), ) if (sharingSection) { sharingSection.scrollIntoView({ behavior: 'smooth' }) } } }, []) const getSubscriptionDetails = () => { if (userProfile?.subscription === 'active') { return `You are currently subscribed to the Plus plan. Your subscription will renew on ${moment( userProfile?.expiration, ).format('MMM DD, YYYY')}.` } else if (userProfile?.subscription === 'canceled') { return `You have cancelled your subscription. Your account will be downgraded to the Free plan on ${moment( userProfile?.expiration, ).format('MMM DD, YYYY')}.` } else { return `You are currently on the Free plan. Upgrade to the Plus plan to unlock more features.` } } const getSubscriptionStatus = () => { if (userProfile?.subscription === 'active') { return `Plus` } else if (userProfile?.subscription === 'canceled') { if (moment().isBefore(userProfile?.expiration)) { return `Plus(until ${moment(userProfile?.expiration).format( 'MMM DD, YYYY', )})` } return `Free` } else { return `Free` } } if (userProfile === null) { return ( ) } if (!userProfile) { return } return (
Circle settings Your account is automatically connected to a Circle when you create or join one. Easily invite friends by sharing the unique Circle code or link below. You'll receive a notification below when someone requests to join your Circle. {userCircles[0]?.userRole === 'member' ? `You part of ${userCircles[0]?.name} ` : `You circle code is:`} {userCircles.length > 0 && userCircles[0]?.userRole === 'member' && ( )} Circle Members {circleMembers.map(member => ( {member.displayName.charAt(0).toUpperCase() + member.displayName.slice(1)} {member.userId === userProfile.id ? '(You)' : ''}{' '} {' '} {member.isActive ? member.role : 'Pending Approval'} {member.isActive ? ( Joined on {moment(member.createdAt).format('MMM DD, YYYY')} ) : ( Request to join{' '} {moment(member.updatedAt).format('MMM DD, YYYY')} )} {member.userId !== userProfile.id && isAdmin && ( )} {userProfile.role === 'admin' && member.userId !== userProfile.id && member.isActive && ( )} ))} {circleMemberRequests.length > 0 && ( Circle Member Requests )} {circleMemberRequests.map(request => ( {request.displayName} wants to join your circle. ))} or if want to join someone else's Circle? Ask them for their unique Circle code or join link. Enter the code below to join their Circle. Enter Circle code: setCircleInviteCode(e.target.value)} size='lg' sx={{ width: '220px', mb: 1, }} /> {circleMembers.find(m => userProfile.id == m.userId)?.role === 'admin' && ( <> Webhook Webhooks allow you to send real-time notifications to other services when events happen in your Circle. Configure a webhook URL to receive real-time updates. {!isPlusAccount(userProfile) && ( Webhook notifications are not available in the Basic plan. Upgrade to Plus to receive real-time updates via webhooks. )} { if (webhookURL === null) { setWebhookURL('') } else { setWebhookURL(null) } }} variant='soft' label='Enable Webhook' disabled={!isPlusAccount(userProfile)} overlay /> Enable webhook notifications for tasks and things updates.{' '} {userProfile && !isPlusAccount(userProfile) && ( Plus Feature )} {webhookURL !== null && ( Webhook URL setWebhookURL(e.target.value)} size='lg' sx={{ width: '220px', mb: 1, }} /> {webhookError && ( {webhookError} )} )} )} {/* WebSocket Settings */} {/* */}
Account Settings Change your account settings, type or update your password Account Type : {getSubscriptionStatus()} {getSubscriptionDetails()} {userProfile?.subscription === 'active' && ( )} {import.meta.env.VITE_IS_SELF_HOSTED === 'true' && ( Password : {changePasswordModal ? ( { if (password) { UpdatePassword(password).then(resp => { if (resp.ok) { showNotification({ type: 'success', message: 'Password changed successfully', }) } else { showNotification({ type: 'error', message: 'Password change failed', }) } }) } setChangePasswordModal(false) }} /> ) : null} )}
Theme preferences Choose how the site looks to you. Select a single theme, or sync with your system and automatically switch between day and night themes.
{/* Modals */} {confirmModalConfig?.isOpen && ( )}
) } export default Settings