aboutsummaryrefslogblamecommitdiffstats
path: root/src/views/Settings/Settings.jsx
blob: d612eeca713b13046f7f42e87083cbb24db2b9c5 (plain) (tree)































































































































































































































































































































































































                                                                                                                              
import {
  Box,
  Button,
  Card,
  Chip,
  CircularProgress,
  Container,
  Divider,
  Input,
  Typography,
} from '@mui/joy'
import moment from 'moment'
import { useContext, useEffect, useState } from 'react'
import { UserContext } from '../../contexts/UserContext'
import Logo from '../../Logo'
import {
  AcceptCircleMemberRequest,
  CancelSubscription,
  DeleteCircleMember,
  GetAllCircleMembers,
  GetCircleMemberRequests,
  GetSubscriptionSession,
  GetUserCircle,
  GetUserProfile,
  JoinCircle,
  LeaveCircle,
} from '../../utils/Fetcher'
import APITokenSettings from './APITokenSettings'
import NotificationSetting from './NotificationSetting'
import ThemeToggle from './ThemeToggle'

const Settings = () => {
  const { userProfile, setUserProfile } = useContext(UserContext)
  const [userCircles, setUserCircles] = useState([])
  const [circleMemberRequests, setCircleMemberRequests] = useState([])
  const [circleInviteCode, setCircleInviteCode] = useState('')
  const [circleMembers, setCircleMembers] = useState([])
  useEffect(() => {
    GetUserProfile().then(resp => {
      resp.json().then(data => {
        setUserProfile(data.res)
      })
    })
    GetUserCircle().then(resp => {
      resp.json().then(data => {
        setUserCircles(data.res ? data.res : [])
      })
    })
    GetCircleMemberRequests().then(resp => {
      resp.json().then(data => {
        setCircleMemberRequests(data.res ? data.res : [])
      })
    })
    GetAllCircleMembers()
      .then(res => res.json())
      .then(data => {
        setCircleMembers(data.res ? data.res : [])
      })
  }, [])

  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 (
      <Container className='flex h-full items-center justify-center'>
        <Box className='flex flex-col items-center justify-center'>
          <CircularProgress
            color='success'
            sx={{ '--CircularProgress-size': '200px' }}
          >
            <Logo />
          </CircularProgress>
        </Box>
      </Container>
    )
  }
  return (
    <Container>
      <div className='grid gap-4 py-4' id='sharing'>
        <Typography level='h3'>Sharing settings</Typography>
        <Divider />
        <Typography level='body-md'>
          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.
        </Typography>
        <Typography level='title-sm' mb={-1}>
          {userCircles[0]?.userRole === 'member'
            ? `You part of ${userCircles[0]?.name} `
            : `You circle code is:`}

          <Input
            value={userCircles[0]?.invite_code}
            disabled
            size='lg'
            sx={{
              width: '220px',
              mb: 1,
            }}
          />
          <Button
            variant='soft'
            onClick={() => {
              navigator.clipboard.writeText(userCircles[0]?.invite_code)
              alert('Code Copied to clipboard')
            }}
          >
            Copy Code
          </Button>
          <Button
            variant='soft'
            sx={{ ml: 1 }}
            onClick={() => {
              navigator.clipboard.writeText(
                window.location.protocol +
                  '//' +
                  window.location.host +
                  `/circle/join?code=${userCircles[0]?.invite_code}`,
              )
              alert('Link Copied to clipboard')
            }}
          >
            Copy Link
          </Button>
          {userCircles.length > 0 && userCircles[0]?.userRole === 'member' && (
            <Button
              sx={{ ml: 1 }}
              onClick={() => {
                const confirmed = confirm(
                  `Are you sure you want to leave your circle?`,
                )
                if (confirmed) {
                  LeaveCircle(userCircles[0]?.id).then(resp => {
                    if (resp.ok) {
                      alert('Left circle successfully.')
                    } else {
                      alert('Failed to leave circle.')
                    }
                  })
                }
              }}
            >
              Leave Circle
            </Button>
          )}
        </Typography>
        <Typography level='title-md'>Circle Members</Typography>
        {circleMembers.map(member => (
          <Card key={member.id} className='p-4'>
            <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
              <Box>
                <Typography level='body-md'>
                  {member.displayName.charAt(0).toUpperCase() +
                    member.displayName.slice(1)}
                  {member.userId === userProfile.id ? '(You)' : ''}{' '}
                  <Chip>
                    {' '}
                    {member.isActive ? member.role : 'Pending Approval'}
                  </Chip>
                </Typography>
                {member.isActive ? (
                  <Typography level='body-sm'>
                    Joined on {moment(member.createdAt).format('MMM DD, YYYY')}
                  </Typography>
                ) : (
                  <Typography level='body-sm' color='danger'>
                    Request to join{' '}
                    {moment(member.updatedAt).format('MMM DD, YYYY')}
                  </Typography>
                )}
              </Box>
              {member.userId !== userProfile.id && member.isActive && (
                <Button
                  disabled={
                    circleMembers.find(m => userProfile.id == m.userId).role !==
                    'admin'
                  }
                  variant='outlined'
                  color='danger'
                  size='sm'
                  onClick={() => {
                    const confirmed = confirm(
                      `Are you sure you want to remove ${member.displayName} from your circle?`,
                    )
                    if (confirmed) {
                      DeleteCircleMember(member.circleId, member.userId).then(
                        resp => {
                          if (resp.ok) {
                            alert('Removed member successfully.')
                          }
                        },
                      )
                    }
                  }}
                >
                  Remove
                </Button>
              )}
            </Box>
          </Card>
        ))}

        {circleMemberRequests.length > 0 && (
          <Typography level='title-md'>Circle Member Requests</Typography>
        )}
        {circleMemberRequests.map(request => (
          <Card key={request.id} className='p-4'>
            <Typography level='body-md'>
              {request.displayName} wants to join your circle.
            </Typography>
            <Button
              variant='soft'
              color='success'
              onClick={() => {
                const confirmed = confirm(
                  `Are you sure you want to accept ${request.displayName}(username:${request.username}) to join your circle?`,
                )
                if (confirmed) {
                  AcceptCircleMemberRequest(request.id).then(resp => {
                    if (resp.ok) {
                      alert('Accepted request successfully.')
                      // reload the page
                      window.location.reload()
                    }
                  })
                }
              }}
            >
              Accept
            </Button>
          </Card>
        ))}
        <Divider> or </Divider>

        <Typography level='body-md'>
          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.
        </Typography>

        <Typography level='title-sm' mb={-1}>
          Enter Circle code:
          <Input
            placeholder='Enter code'
            value={circleInviteCode}
            onChange={e => setCircleInviteCode(e.target.value)}
            size='lg'
            sx={{
              width: '220px',
              mb: 1,
            }}
          />
          <Button
            variant='soft'
            onClick={() => {
              const confirmed = confirm(
                `Are you sure you want to leave you circle and join '${circleInviteCode}'?`,
              )
              if (confirmed) {
                JoinCircle(circleInviteCode).then(resp => {
                  if (resp.ok) {
                    alert(
                      'Joined circle successfully, wait for the circle owner to accept your request.',
                    )
                  }
                })
              }
            }}
          >
            Join Circle
          </Button>
        </Typography>
      </div>

      <div className='grid gap-4 py-4' id='account'>
        <Typography level='h3'>Account Settings</Typography>
        <Divider />
        <Typography level='body-md'>
          Change your account settings, including your password, display name
        </Typography>
        <Typography level='title-md' mb={-1}>
          Account Type : {getSubscriptionStatus()}
        </Typography>
        <Typography level='body-sm'>{getSubscriptionDetails()}</Typography>
        <Box>
          <Button
            sx={{
              width: '110px',
              mb: 1,
            }}
            disabled={
              userProfile?.subscription === 'active' ||
              moment(userProfile?.expiration).isAfter(moment())
            }
            onClick={() => {
              GetSubscriptionSession().then(data => {
                data.json().then(data => {
                  console.log(data)
                  window.location.href = data.sessionURL
                  // open in new window:
                  // window.open(data.sessionURL, '_blank')
                })
              })
            }}
          >
            Upgrade
          </Button>

          {userProfile?.subscription === 'active' && (
            <Button
              sx={{
                width: '110px',
                mb: 1,
                ml: 1,
              }}
              variant='outlined'
              onClick={() => {
                CancelSubscription().then(resp => {
                  if (resp.ok) {
                    alert('Subscription cancelled.')
                    window.location.reload()
                  }
                })
              }}
            >
              Cancel
            </Button>
          )}
        </Box>
      </div>
      <NotificationSetting />
      <APITokenSettings />
      <div className='grid gap-4 py-4'>
        <Typography level='h3'>Theme preferences</Typography>
        <Divider />
        <Typography level='body-md'>
          Choose how the site looks to you. Select a single theme, or sync with
          your system and automatically switch between day and night themes.
        </Typography>
        <ThemeToggle />
      </div>
    </Container>
  )
}

export default Settings