Skip to content

Commit

Permalink
Implement get request and svg generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jetsaii committed Jan 25, 2021
1 parent 5feefe9 commit dccffe8
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 47 deletions.
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="leetcode-stats"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
Expand All @@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>leetcode-stats</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
4 changes: 2 additions & 2 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "leetcode-stats",
"name": "leetcode-stats",
"icons": [
{
"src": "favicon.ico",
Expand Down
8 changes: 3 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const mainTheme = createMuiTheme({
main: '#33eb91',
},
secondary: {
main: '#33eb91',
main: '#f73378',
},
// Background colors
info: {
Expand All @@ -23,10 +23,8 @@ const mainTheme = createMuiTheme({
},
})

const useStyles = makeStyles((theme) => ({
root: {
paddingTop: theme.spacing(20),
},
const useStyles = makeStyles(() => ({
root: {},
}))

function App(): JSX.Element {
Expand Down
75 changes: 63 additions & 12 deletions src/components/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,29 @@ import ImageIcon from '@material-ui/icons/Image'
import BorderColorIcon from '@material-ui/icons/BorderColor'
import IconButton from './IconButton'
import { ThemeType, defaultTheme, themes } from '../static/themes'
import getStatsReq from '../utils/getStats'
import { getStatsReq } from '../utils/getStats'
import { getSvg } from '../utils/getSvg'

const useStyles = makeStyles((theme) => ({
paper: {
margin: 'auto',
backgroundColor: theme.palette.info.light,
height: theme.spacing(70),
width: '40%',
height: '100%',
width: '50%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontSize: theme.spacing(5),
},
successStatus: {
color: theme.palette.primary.main,
},
errorStatus: {
color: theme.palette.secondary.main,
},
colSection: {
padding: theme.spacing(2),
display: 'flex',
Expand All @@ -46,19 +54,38 @@ function Content(): JSX.Element {
// Username
const nameRef = useRef('')

const getValue = (ref: React.MutableRefObject<string>): string => {
const cur = (ref.current as unknown) as HTMLTextAreaElement
return cur.value
}

// Theme
const [theme, setTheme] = useState<ThemeType>(defaultTheme)

const handleThemeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const target = (event.target as unknown) as ThemeType
setTheme(target)
const { target } = event
const newTheme = JSON.parse(target.value) as ThemeType
setTheme(newTheme)
}

// Status
const [statusText, setStatusText] = useState('Status: awaiting generation')

// Action buttons
const [generated, setGenerated] = useState(false)
const [imgCopied, setImgCopied] = useState(false)
const [mdCopied, setMdcopied] = useState(false)

// Dynamic svg component
const [svg, setSvg] = useState('')

const resetStates = () => {
setImgCopied(false)
setMdcopied(false)
setSvg('')
setGenerated(false)
}

// onClick function for git button
const gitOnClick = () => {
window.open(
Expand All @@ -70,8 +97,27 @@ function Content(): JSX.Element {

// onClick function for generate button
const genOnClick = () => {
setGenerated(true)
getStatsReq()
resetStates()
setStatusText('Status: generating...')

const username = getValue(nameRef)
// User did not enter username
if (username === '') {
setStatusText('Status: please enter username above')
return
}

const stats = getStatsReq(username)
stats.then((data) => {
if (data.status === 'success') {
setSvg(getSvg({ stats: data, username, theme }))
setGenerated(true)
setStatusText('Status: successfully generated')
} else {
setGenerated(false)
setStatusText(`Status: ${data.message}`)
}
})
}

// onClick function for copy image button
Expand All @@ -89,7 +135,7 @@ function Content(): JSX.Element {
<Paper elevation={12} className={classes.paper}>
<div className={classes.colSection}>
<Typography
color="secondary"
color="primary"
align="center"
variant="h2"
className={classes.text}>
Expand All @@ -98,7 +144,7 @@ function Content(): JSX.Element {
<IconButton
text="GitHub"
icon={<GitHubIcon />}
color="secondary"
color="primary"
onClick={gitOnClick}
/>
</div>
Expand All @@ -121,7 +167,7 @@ function Content(): JSX.Element {
fullWidth
select
label="Theme"
value={theme.value}
value={JSON.stringify(theme)}
onChange={handleThemeChange}
InputLabelProps={{
className: classes.textFieldLabel,
Expand All @@ -130,20 +176,25 @@ function Content(): JSX.Element {
className: classes.textInput,
}}>
{themes.map((themeX) => (
<MenuItem key={themeX.value} value={themeX.value}>
<MenuItem key={themeX.value} value={JSON.stringify(themeX)}>
{themeX.value}
</MenuItem>
))}
</TextField>
</div>
<div
className={generated ? classes.successStatus : classes.errorStatus}>
{statusText}
</div>
<div className={classes.rowSection}>
<IconButton
text={generated ? 'Successfully Generated' : 'Generate'}
text="Generate"
icon={<BubbleChartIcon />}
color="primary"
onClick={genOnClick}
/>
</div>
<div dangerouslySetInnerHTML={{ __html: svg }} />
{generated && (
<div className={classes.rowSection}>
<IconButton
Expand Down
27 changes: 15 additions & 12 deletions src/static/themes.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type ThemeType = {
value: string
background: string
title: string
text: string
circle: string
easy: string
Expand All @@ -9,22 +10,24 @@ export type ThemeType = {
}
export const defaultTheme = {
value: 'Light',
background: '',
text: '',
circle: '',
easy: '',
med: '',
hard: '',
background: '#fffefe',
title: '#2f80ed',
text: '#333',
circle: '#2f80ed',
easy: '#00e676',
med: '#ff9100',
hard: '#f73378',
}
export const themes = [
defaultTheme,
{
value: 'Dark',
background: '',
text: '',
circle: '',
easy: '',
med: '',
hard: '',
background: '#121212',
title: '#fe428e',
text: '#a9fef7',
circle: '#fe428e',
easy: '#00e676',
med: '#ff9100',
hard: '#f73378',
},
]
26 changes: 12 additions & 14 deletions src/utils/getStats.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import axios from 'axios'

const ENDPOINT = ''
const ENDPOINT = 'https://leetcode-stats-api.herokuapp.com/'

interface StatsResponse {
export interface StatsResponse {
status: string
message: string
totalSolved?: number
totalQuestions?: number
easySolved?: number
totalEasy?: number
mediumSolved?: number
Expand All @@ -17,16 +19,12 @@ interface StatsResponse {
reputation?: number
}

const getStatsReq = (): StatsResponse => {
axios
.get(ENDPOINT)
.then((response) => {
return response
})
.catch(() => {
return { status: 'error' }
})
return { status: 'error' }
export const getStatsReq = async (username: string): Promise<StatsResponse> => {
try {
const response = await axios.get(`${ENDPOINT}/${username}/`)
return response.data as StatsResponse
} catch {
const errMsg = 'could not reach backend, try again later.'
return { status: 'error', message: errMsg }
}
}

export default getStatsReq
Loading

0 comments on commit dccffe8

Please sign in to comment.