Skip to content

Commit

Permalink
refactor(database logic) & show(toast message for survey creation limit)
Browse files Browse the repository at this point in the history
  • Loading branch information
visrut-at-incubyte committed Sep 13, 2023
1 parent ea9e5e1 commit b510278
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 23 deletions.
43 changes: 43 additions & 0 deletions app/components/Toast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use client'

import React, { useEffect, useState } from 'react'

type ToastProps = {
message: string
duration: number
onClose: () => void
}

export default function Toast({ message, duration, onClose }: ToastProps) {
const [showToast, setShowToast] = useState(false)

useEffect(() => {
setShowToast(true)

setTimeout(() => {
setShowToast(false)
onClose()
}, duration)
}, [duration, onClose])

return (
showToast && (
<div className='fixed flex gap-x-5 top-3.5 left-1/2 transform -translate-x-1/2 w-3/4 bg-red-500 bg-opacity-70 text-white py-2 px-4 rounded shadow-lg transition-opacity duration-300 opacity-100 hover:opacity-75'>
<svg
xmlns='http://www.w3.org/2000/svg'
className='stroke-current shrink-0 h-6 w-6'
fill='none'
viewBox='0 0 24 24'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='2'
d='M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z'
/>
</svg>
<span>{message}</span>
</div>
)
)
}
32 changes: 9 additions & 23 deletions app/create-survey/api/route.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
import clientPromise from '@/app/mongodb'
import { NextResponse } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
import { createHash, getClientIP } from '@/app/utils'
import { getClientIP } from '@/app/utils'
import clientPromise from '@/app/mongodb'
import { SurveyDatabase } from '@/app/database'

export async function POST(request: Request) {
const ip = getClientIP(request)
const hash = createHash(ip!)

const client = await clientPromise
const db = client.db('survey-db')
const creatorHistory = await db.collection('creator-ip-hash').findOne({ ipHash: hash })

const uuid = uuidv4()

if (creatorHistory === null) {
await db.collection('creator-ip-hash').insertOne({ ipHash: hash, count: 1 })
} else {
const prevCount = creatorHistory.count
const database = new SurveyDatabase(db)

if (prevCount >= 3) {
return NextResponse.json({ error: 'API Limit is reached' }, { status: 429 })
}

await db.collection('creator-ip-hash').updateOne({ ipHash: hash }, { $set: { count: prevCount + 1 } })
try {
const uuid: string = await database.createSurvey(ip!, await request.json())
return NextResponse.json({ 'survey-id': uuid }, { status: 201 })
} catch (error) {
return NextResponse.json({ error: (error as any).message }, { status: 429 })
}

const survey = await request.json()
survey.creatorIpHash = hash
survey.uuid = uuid
await db.collection('survey-templates').insertOne(survey)

return NextResponse.json({ 'survey-id': uuid }, { status: 201 })
}
14 changes: 14 additions & 0 deletions app/create-survey/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Question, QuestionType } from '../models/types'
import { useAppContext } from '../context/AppContext'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import Toast from '../components/Toast'

export default function CreateSurvey() {
const router = useRouter()
Expand All @@ -23,6 +24,7 @@ export default function CreateSurvey() {
} = useAppContext()

const [isFinishLoading, setIsFinishLoading] = useState(false)
const [showError, setShowError] = useState(false)

const goLeft = () => {
if (currentQuestionNumber > 0) {
Expand Down Expand Up @@ -60,7 +62,12 @@ export default function CreateSurvey() {
})
})

if (res.status === 429) {
setShowError(true)
}

setIsFinishLoading(false)
// setShowError(false)

const data = await res.json()
const surveyId = data['survey-id']
Expand All @@ -73,6 +80,13 @@ export default function CreateSurvey() {

return (
<main className='flex flex-col h-screen'>
{showError && (
<Toast
duration={3000}
message='API Limit is reached for creating survey!'
onClose={() => setShowError(false)}
/>
)}
<nav className='flex justify-center p-3'>
<input type='text' className='input' value={name} onChange={editSurveyName} data-testid='survey-name-input' />
</nav>
Expand Down
38 changes: 38 additions & 0 deletions app/database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Db } from 'mongodb'
import { v4 as uuidv4 } from 'uuid'
import { createHash } from './utils'

export class SurveyDatabase {
constructor(private readonly db: Db) {}

public async createSurvey(ip: string, survey: any): Promise<string> {
if (!(await this.isUserSurveyLimitReached(ip))) {
const uuid = uuidv4()
survey.creatorIpHash = createHash(ip)
survey.uuid = uuid
await this.db.collection('survey-templates').insertOne(survey)
return uuid
}
throw new Error('API Limit is reached')
}

private async isUserSurveyLimitReached(ip: string) {
const hash = createHash(ip)
const creatorHistory = await this.db.collection('creator-ip-hash').findOne({ ipHash: hash })

if (creatorHistory === null) {
await this.db.collection('creator-ip-hash').insertOne({ ipHash: hash, count: 1 })
return false
}

const prevCount = creatorHistory.count

if (prevCount >= 3) {
return true
}

await this.db.collection('creator-ip-hash').updateOne({ ipHash: hash }, { $set: { count: prevCount + 1 } })

return false
}
}

0 comments on commit b510278

Please sign in to comment.