From 48493ce9d864008e4c1b14b9d6cce0dbd9079383 Mon Sep 17 00:00:00 2001 From: devsargam Date: Tue, 26 Mar 2024 03:41:27 +0530 Subject: [PATCH] feat: setup refresh option --- src/actions/refresh-db/index.ts | 66 +++++++++++++++++++++++++++++++++ src/components/RefreshDb.tsx | 31 ++++++++++++++++ src/db/Cache.ts | 6 ++- src/utiles/appx-check-mail.ts | 24 ++++++++++++ src/utiles/appx.ts | 22 ++--------- 5 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 src/actions/refresh-db/index.ts create mode 100644 src/components/RefreshDb.tsx create mode 100644 src/utiles/appx-check-mail.ts diff --git a/src/actions/refresh-db/index.ts b/src/actions/refresh-db/index.ts new file mode 100644 index 000000000..bfec769ff --- /dev/null +++ b/src/actions/refresh-db/index.ts @@ -0,0 +1,66 @@ +'use server'; +import db from '@/db'; +import { Cache } from '@/db/Cache'; +import { getAllCourses } from '@/db/course'; +import { checkUserEmailForPurchase } from '@/utiles/appx-check-mail'; +import { Course } from '@prisma/client'; + +type RefreshDbFn = (args: { userId: string; email: string }) => Promise<{ + error: boolean; + message: string; +}>; + +export const refreshDb: RefreshDbFn = async ({ userId, email }) => { + // Only allow user to refetch every minute + if (Cache.getInstance().get('rate-limit', [userId])) { + return { + error: true, + message: 'Wait sometime before refetching', + }; + } + + const allCourses = (await getAllCourses()) as Course[]; + + // Check which course the user has purchased + const userCourses = await db.userPurchases.findMany({ + where: { + userId, + }, + }); + + const coursesWithoutUser = allCourses.filter((course) => { + return !userCourses.some((userCourse) => userCourse.courseId === course.id); + }); + + const responses: Course[] = []; + + const promises = coursesWithoutUser + .filter((x) => !x.openToEveryone) + .map(async (course) => { + const courseId = course.appxCourseId.toString(); + const data = await checkUserEmailForPurchase(email, courseId); + if (data.data === '1') { + responses.push(course); + } + }); + + await Promise.all(promises); + + responses.forEach(async (res) => { + try { + await db.userPurchases.create({ + data: { + userId, + courseId: res.id, + }, + }); + } catch { + return { error: true, message: 'Unable to insert courses' }; + } + }); + + Cache.getInstance().evict('courses', [email]); + Cache.getInstance().set('rate-limit', [userId], true, 60); + + return { error: false, message: 'Refetched Courses' }; +}; diff --git a/src/components/RefreshDb.tsx b/src/components/RefreshDb.tsx new file mode 100644 index 000000000..8303a6efa --- /dev/null +++ b/src/components/RefreshDb.tsx @@ -0,0 +1,31 @@ +'use client'; +import { refreshDb } from '@/actions/refresh-db'; +import { Button } from './ui/button'; +import { toast } from 'sonner'; +import { useSession } from 'next-auth/react'; + +export function RefreshDb() { + const session = useSession(); + console.log(session); + + const handleClick = async () => { + // @ts-ignore + const res = await refreshDb({ userId: session.data.user.id }); + if (res.error) { + toast.error(res.message); + } else { + toast.info(res.message); + } + }; + + if (session.status === 'loading') return <>Loading...; + + return ( +
+

Don't see all your courses?

+ +
+ ); +} diff --git a/src/db/Cache.ts b/src/db/Cache.ts index da447951c..bc0527e5b 100644 --- a/src/db/Cache.ts +++ b/src/db/Cache.ts @@ -51,5 +51,9 @@ export class Cache { return entry.value; } - evict() {} + evict(type: string, args: string[]) { + const key = `${type} ${JSON.stringify(args)}`; + this.inMemoryDb.delete(key); + return null; + } } diff --git a/src/utiles/appx-check-mail.ts b/src/utiles/appx-check-mail.ts new file mode 100644 index 000000000..5c54d745a --- /dev/null +++ b/src/utiles/appx-check-mail.ts @@ -0,0 +1,24 @@ +const APPX_AUTH_KEY = process.env.APPX_AUTH_KEY; +const APPX_CLIENT_SERVICE = process.env.APPX_CLIENT_SERVICE; +const APPX_BASE_API = process.env.APPX_BASE_API; + +const baseUrl = `${APPX_BASE_API}/get/checkemailforpurchase`; + +const headers = { + 'Client-Service': APPX_CLIENT_SERVICE, + 'Auth-Key': APPX_AUTH_KEY, +}; + +export async function checkUserEmailForPurchase( + email: string, + courseId: string, +) { + const params = new URLSearchParams({ + email, + itemtype: '10', + itemid: courseId, + }); + //@ts-ignore + const response = await fetch(`${baseUrl}?${params}`, { headers }); + return await response.json(); +} diff --git a/src/utiles/appx.ts b/src/utiles/appx.ts index d831e7725..a12bd0209 100644 --- a/src/utiles/appx.ts +++ b/src/utiles/appx.ts @@ -8,10 +8,8 @@ import { Course } from '@/store/atoms'; import { getServerSession } from 'next-auth'; import { Cache } from '@/db/Cache'; import prisma from '@/db'; +import { checkUserEmailForPurchase } from './appx-check-mail'; -const APPX_AUTH_KEY = process.env.APPX_AUTH_KEY; -const APPX_CLIENT_SERVICE = process.env.APPX_CLIENT_SERVICE; -const APPX_BASE_API = process.env.APPX_BASE_API; const LOCAL_CMS_PROVIDER = process.env.LOCAL_CMS_PROVIDER; export async function getPurchases(email: string) { @@ -86,27 +84,13 @@ export async function getPurchases(email: string) { return allCourses; } - const baseUrl = `${APPX_BASE_API}/get/checkemailforpurchase`; - - const headers = { - 'Client-Service': APPX_CLIENT_SERVICE, - 'Auth-Key': APPX_AUTH_KEY, - }; - const responses: Course[] = []; const promises = courses .filter((x) => !x.openToEveryone) .map(async (course) => { - const params = new URLSearchParams({ - email, - itemtype: '10', - itemid: course.appxCourseId.toString(), - }); - //@ts-ignore - const response = await fetch(`${baseUrl}?${params}`, { headers }); - const data = await response.json(); - + const courseId = course.appxCourseId.toString(); + const data = await checkUserEmailForPurchase(email, courseId); if (data.data === '1') { responses.push(course); }