Commit c0aaece6 authored by dasunx's avatar dasunx

telegram connect added

parent 64622521
import { publicFetch } from '../util/fetcher'
export async function disconnectTelegram(username) {
try {
const response = await publicFetch.delete(`user/disconnect-telegram`, {
data: { username: username }
})
if (response.status === 200) {
return true
}
} catch (e) {
console.log('REST error: ', e)
}
return false
}
import React from 'react'
const Verified = ({ color = '#1c9cea' }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill={color}
className="bi bi-patch-check-fill"
viewBox="0 0 16 16"
>
<path d="M10.067.87a2.89 2.89 0 0 0-4.134 0l-.622.638-.89-.011a2.89 2.89 0 0 0-2.924 2.924l.01.89-.636.622a2.89 2.89 0 0 0 0 4.134l.637.622-.011.89a2.89 2.89 0 0 0 2.924 2.924l.89-.01.622.636a2.89 2.89 0 0 0 4.134 0l.622-.637.89.011a2.89 2.89 0 0 0 2.924-2.924l-.01-.89.636-.622a2.89 2.89 0 0 0 0-4.134l-.637-.622.011-.89a2.89 2.89 0 0 0-2.924-2.924l-.89.01-.622-.636zm.287 5.984-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7 8.793l2.646-2.647a.5.5 0 0 1 .708.708z" />
</svg>
)
}
export default Verified
import { Snackbar } from '@material-ui/core'
import { Alert } from '@material-ui/lab'
import React, { useEffect } from 'react'
const NotificationSnack = ({
message,
severity,
showSnackbar,
setShowSnackbar,
onClose = () => {},
autoHideDuration = 5000,
vertical = 'bottom',
horizontal = 'left'
}) => {
const [open, setOpen] = React.useState(showSnackbar)
const onCloseSnack = (event, reason) => {
setOpen(false)
setShowSnackbar(false)
onClose(event, reason)
}
useEffect(() => {
setOpen(showSnackbar)
}, [showSnackbar])
return (
<Snackbar
open={open}
autoHideDuration={autoHideDuration}
onClose={onCloseSnack}
anchorOrigin={{ vertical, horizontal }}
>
<Alert onClose={onCloseSnack} severity={severity} sx={{ width: '100%' }}>
{message}
</Alert>
</Snackbar>
)
}
export default NotificationSnack
import { Box, Typography } from '@material-ui/core'
import { Alert, AlertTitle } from '@material-ui/lab'
import React, { useContext, useEffect, useState } from 'react'
import { AuthContext } from '../../../store/auth'
import { FetchContext } from '../../../store/fetch'
import { Spinner } from '../../icons'
import styles from './TelegramConnect.module.css'
const TelegramConnect = () => {
const [code, setCode] = useState('')
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState('')
const [isConnected, setIsConnected] = useState(false)
const { authAxios } = useContext(FetchContext)
const { authState } = useContext(AuthContext)
const isTelegramConnected = authState.userInfo?.isTelegramConnected
const username = authState.userInfo?.username
const getTelegramCode = async () => {
try {
const { data, status } = await authAxios.post('/user/createtgcode', {
username
})
if (status === 200) {
if (data.user.isTelegramConnected) {
setIsConnected(true)
setIsLoading(false)
setError('Already connected')
} else {
setCode(data.user.telegramConnectionCode)
setIsLoading(false)
}
}
} catch (e) {
if (e.response.status === 400) {
setIsConnected(true)
setIsLoading(false)
setError('Already connected')
} else {
setError('Something went wrong while creating the code')
setIsLoading(false)
}
}
}
useEffect(() => {
if (!isTelegramConnected) {
getTelegramCode()
} else {
setIsLoading(false)
setIsConnected(true)
}
}, [])
return (
<Box sx={{ mt: '10px' }}>
<Typography variant="h5" align="center">
Just one step away from connecting your Telegram account
</Typography>
{isLoading ? (
<div className="loading">
<Spinner />
</div>
) : isConnected ? (
<div className={styles.tg_connect_container}>
<Alert variant="filled" severity="success">
<AlertTitle>Conencted</AlertTitle>
You are already connected to Telegram
</Alert>
</div>
) : (
<div className={styles.tg_connect_container}>
<Typography variant="h3" align="center">
Your code is
</Typography>
<div className={styles.code_number_container}>
{code &&
Array.from(String(code), Number).map((char, index) => {
return (
<span className={styles.code_number} key={index}>
{char}
</span>
)
})}
</div>
<Typography variant="h6" align="center">
Once you've sent the code, click the Verify button.
</Typography>
</div>
)}
</Box>
)
}
export default TelegramConnect
.tg_connect_container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #fff;
position: relative;
margin-top: 16px;
padding: 30px 0;
}
.code_number_container {
display: flex;
margin: 20px 0;
}
.code_number {
border: 1px solid var(--blue-500);
margin: 10px;
padding: 10px 15px;
border-radius: 5px;
/* display: block; */
font-weight: 600;
font-size: 20px;
}
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Typography
} from '@material-ui/core'
import React, { useContext, useState } from 'react'
import { disconnectTelegram } from '../../../actions/telegram'
import { AuthContext } from '../../../store/auth'
const TelegramDisconnect = ({ username, setActiveStep, setSnackbar }) => {
const [open, setOpen] = useState(false)
const { authState, setAuthState } = useContext(AuthContext)
const disconnect = async () => {
setOpen(() => false)
const isDisconnected = await disconnectTelegram(username)
if (isDisconnected) {
authState.userInfo.isTelegramConnected = false
setAuthState(authState)
setActiveStep(0)
setSnackbar({
show: true,
message: 'Telegram account disconnected',
severity: 'success'
})
}
}
return (
<Box sx={{ mt: '10px' }}>
<Typography variant="h5" align="center">
All done! You are now connected with the Telegram bot.
</Typography>
<Box
style={{ background: '#fff' }}
display="flex"
flexDirection="column"
margin="auto"
padding="20px 10px"
>
<Typography variant="h6" align="center">
You can disconnect the bot from your account by clicking the button
below.
</Typography>
<Button
variant="outlined"
color="error"
onClick={() => setOpen(!open)}
style={{ margin: 'auto', background: '#FF1744', color: '#fff' }}
>
Disconnect
</Button>
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>Disconnect Telegram Bot</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description" color="#000">
By disconnecting the bot, you will no longer be able to use the
bot to send messages to your account. (Ask questions) In order to
reconnect the bot, you will need to follow the steps again.
</DialogContentText>
<img
src="https://i.imgur.com/ccH89kQ.jpg"
width="80%"
style={{ display: 'block', margin: 'auto' }}
/>
</DialogContent>
<DialogActions>
<Button
variant="outlined"
color="inherit"
onClick={() => setOpen(false)}
>
Cancel
</Button>
<Button
variant="outlined"
onClick={disconnect}
autoFocus
style={{ border: '1px solid #FF1744', color: '#FF1744' }}
>
Disconnect
</Button>
</DialogActions>
</Dialog>
</Box>
</Box>
)
}
export default TelegramDisconnect
import { Typography } from '@material-ui/core'
import React from 'react'
import Button from '../../button'
import Verified from '../../icons/Verified'
import styles from './TelegramStatus.module.css'
const TelegramStatus = ({ isTelegramConnected }) => {
return (
<div className={styles.telegramStatus_wrapper}>
{isTelegramConnected ? (
<div className={styles.telegramStatus}>
<Typography variant="h6">Telegram connected</Typography>
<Verified />
</div>
) : (
<div className={styles.telegramStatus}>
<Typography variant="h6">Telegram not connected</Typography>
</div>
)}
<Button href="/telegram/connect" primary full>
{isTelegramConnected ? 'Disconnect' : 'Connect'}
</Button>
</div>
)
}
export default TelegramStatus
.telegramStatus_wrapper {
margin-top: 1em;
display: flex;
flex-direction: column;
gap: 0.5em;
}
.telegramStatus {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
}
import { Box, Step, StepLabel, Stepper, Typography } from '@material-ui/core'
import React, { useContext, useEffect, useState } from 'react'
import Button from '../../button'
import TelegramInstructions from '../tg-connect-instructions/TelegramInstructions'
import Styles from './TelegramWrapper.module.css'
import { createTheme } from '@material-ui/core'
import { ThemeProvider } from '@material-ui/styles'
import TelegramConnect from '../telegram-connect/TelegramConnect'
import { FetchContext } from '../../../store/fetch'
import { Alert, AlertTitle } from '@material-ui/lab'
import { AuthContext } from '../../../store/auth'
import TelegramDisconnect from '../telegram-disconnect/TelegramDisconnect'
import NotificationSnack from '../../notification-snack/NotificationSnack'
const theme = createTheme({
overrides: {
MuiStepIcon: {
root: {
'&$completed': {
color: 'green'
},
'&$active': {
color: 'var(--blue-500)'
}
},
active: {},
completed: {}
}
}
})
const steps = ['Instructions', 'Verification', 'Success']
const TelegramWrapper = () => {
const [activeStep, setActiveStep] = React.useState(0)
const { authAxios } = useContext(FetchContext)
const [conenctError, setConnectError] = useState('')
const { authState, setAuthState } = useContext(AuthContext)
const [snackbar, setSnackbar] = useState({
show: false,
message: '',
severity: 'success'
})
const username = authState.userInfo?.username
const isTelegramConnected = authState.userInfo?.isTelegramConnected
useEffect(() => {
if (isTelegramConnected) {
setActiveStep(2)
}
}, [isTelegramConnected])
const checkConnection = async () => {
try {
const response = await authAxios.post(
'/user/verify-telegram-connection',
{ username: username }
)
if (response.status === 200) {
setActiveStep((prevActiveStep) => prevActiveStep + 1)
if (!authState.userInfo.isTelegramConnected) {
authState.userInfo.isTelegramConnected = true
setAuthState(authState)
}
}
} catch (error) {
setConnectError('Not verified yet.')
}
}
const handleNext = async () => {
if (activeStep === 1) {
if (!isTelegramConnected) {
await checkConnection()
} else {
setActiveStep((prevActiveStep) => prevActiveStep + 1)
}
} else {
if (activeStep === steps.length - 1) {
window.location.replace('/users/' + username)
} else {
setActiveStep((prevActiveStep) => prevActiveStep + 1)
}
}
}
const handleBack = () => {
setConnectError('')
setActiveStep((prevActiveStep) => prevActiveStep - 1)
}
const getStepContent = () => {
switch (activeStep) {
case 0:
return <TelegramInstructions />
case 1:
return <TelegramConnect />
case 2:
return (
<TelegramDisconnect
username={username}
setActiveStep={setActiveStep}
setSnackbar={setSnackbar}
/>
)
default:
return 'Unknown step'
}
}
return (
<>
<ThemeProvider theme={theme}>
<Stepper activeStep={activeStep} className={Styles.stepper}>
{steps.map((step) => {
return (
<Step key={step}>
<StepLabel>
<Typography variant="h6">{step}</Typography>
</StepLabel>
</Step>
)
})}
</Stepper>
</ThemeProvider>
<div className={Styles.telegram_wrapper}>
{getStepContent()}
{!!conenctError && (
<Alert severity="error">
<AlertTitle>Error</AlertTitle>
{conenctError}
<strong>Please try again</strong>
</Alert>
)}
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
<Button
secondary
color="inherit"
disabled={activeStep === 0}
onClick={handleBack}
sx={{ mr: 1 }}
>
Back
</Button>
<Box sx={{ flex: '1 1 auto' }} />
<Button onClick={handleNext} primary style={{ padding: 'auto 30px' }}>
{activeStep === steps.length - 1
? 'Go home'
: activeStep === 1
? isTelegramConnected
? 'Next'
: 'Verify'
: 'Next'}
</Button>
</Box>
<NotificationSnack
message={snackbar.message}
showSnackbar={snackbar.show}
severity={snackbar.severity}
setShowSnackbar={(show) => setSnackbar({ ...snackbar, show })}
/>
</div>
</>
)
}
export default TelegramWrapper
.telegram_wrapper {
margin: 10px 0;
padding: 10px;
background-color: #752d870d;
border-radius: 10px;
}
.stepper {
background-color: transparent;
}
import * as React from 'react'
import Box from '@material-ui/core/Box'
import Stepper from '@material-ui/core/Stepper'
import Step from '@material-ui/core/Step'
import StepLabel from '@material-ui/core/StepLabel'
import StepContent from '@material-ui/core/StepContent'
import Button from '../../button'
import Paper from '@material-ui/core/Paper'
import Typography from '@material-ui/core/Typography'
import { createTheme } from '@material-ui/core'
import { ThemeProvider } from '@material-ui/styles'
import Styles from './TelegramInstructions.module.css'
const theme = createTheme({
overrides: {
MuiStepIcon: {
root: {
'&$completed': {
color: 'green'
},
'&$active': {
color: 'var(--blue-500)'
}
},
active: {},
completed: {}
}
}
})
const steps = [
{
label: 'Open ProbExpert Bot in your telegram app',
description: (
<>
<span className={Styles.instruction_text}>
Open your telegram app and search for probexpertbot or{' '}
<a target="_blank" href="https://t.me/probexpertBot">
Click here to open the @probExpertbot
</a>
</span>
<img
src="https://i.imgur.com/ikaBrzZ.gif"
alt="probexpert bot searching gif"
className={Styles.instruction_image}
/>
</>
)
},
{
label: 'Start the bot and send your username',
description: (
<>
<span className={Styles.instruction_text}>
Start the bot, and use command /connect to connect your account. Give
your username to bot, Then go to next step and copy the code, and send
it using the bot.
</span>
<img
src="https://i.imgur.com/hJDfRlL.gif"
alt="probexpert bot starting gif"
// className={Styles.instruction_image}
/>
</>
)
}
]
export default function InstructionStepper() {
const [activeStep, setActiveStep] = React.useState(0)
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1)
}
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1)
}
const handleReset = () => {
setActiveStep(0)
}
return (
<Box sx={{ mt: 2 }}>
<ThemeProvider theme={theme}>
<Stepper activeStep={activeStep} orientation="vertical">
{steps.map((step, index) => (
<Step key={step.label} sx={{ color: 'red' }}>
<StepLabel
optional={
index === 1 ? (
<Typography variant="caption">Last step</Typography>
) : null
}
>
<Typography variant="h6">{step.label}</Typography>
</StepLabel>
<StepContent>
<Typography>{step.description}</Typography>
<Box sx={{ mb: 2, mt: 1 }}>
<div>
<Button
primary
variant="contained"
onClick={handleNext}
style={{ marginRight: '10px' }}
>
{index === steps.length - 1 ? 'Finish' : 'Continue'}
</Button>
{index !== 0 && (
<Button
secondary
disabled={index === 0}
onClick={handleBack}
>
Back
</Button>
)}
</div>
</Box>
</StepContent>
</Step>
))}
</Stepper>
</ThemeProvider>
{activeStep === steps.length && (
<Paper square elevation={0} style={{ padding: '20px' }}>
<Typography variant="h5">
Visit next step to find the 6 digit code
</Typography>
</Paper>
)}
</Box>
)
}
import React, { useContext, useEffect } from 'react'
import { Box, Typography } from '@material-ui/core'
import { AuthContext } from '../../../store/auth'
import InstructionStepper from './InstructionStepper'
const TelegramInstructions = () => {
const { isAuthenticated, authState } = useContext(AuthContext)
const username = authState.userInfo?.username
useEffect(() => {
// if (!isAuthenticated()) {
// window.location.href = '/'
// }
}, [])
return (
<Box sx={{ mt: '10px' }}>
<Typography variant="h5" align="center">
Hi{username ? ` ${username},` : ','} Let's connect your Telegram account
</Typography>
<InstructionStepper />
</Box>
)
}
export default TelegramInstructions
.instruction_text {
padding: 10px 5px;
display: block;
background: #faf4ec;
width: fit-content;
border-radius: 5 px;
}
.instruction_image {
display: block;
height: 540px;
margin: 10px 0;
}
import React from 'react'
import Head from 'next/head'
import Layout from '../../components/layout'
import DetailPageContainer from '../../components/detail-page-container'
import PageTitle from '../../components/page-title'
import TelegramWrapper from '../../components/telegram/telegram-wrapper/TelegramWrapper'
const Connect = () => {
const isClient = typeof window === 'object'
return (
<Layout extra={false}>
<Head>
<title>Connect your telegram account</title>
<link rel="canonical" href={isClient && window.location.href}></link>
</Head>
<PageTitle title="Connect your Telegram account" />
<TelegramWrapper />
</Layout>
)
}
export default Connect
import { createMuiTheme } from '@material-ui/core/styles';
import { red } from '@material-ui/core/colors';
// Create a theme instance.
const theme = createMuiTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
background: {
default: '#fff',
},
},
});
export default theme;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment