diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 3fed3135..00000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "printWidth": 80, - "useTabs": false, - "semi": true, - "singleQuote": true, - "trailingComma": "es5", - "bracketSpacing": true, - "arrowParens": "avoid", - "proseWrap": "always" -} diff --git a/frontend/.prettierrc b/frontend/.prettierrc index 3fed3135..e6e05952 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -6,5 +6,8 @@ "trailingComma": "es5", "bracketSpacing": true, "arrowParens": "avoid", - "proseWrap": "always" + "proseWrap": "always", + + "plugins": ["prettier-plugin-tailwindcss"], + "tailwindFunctions": ["clsx", "cn"] } diff --git a/frontend/README.md b/frontend/README.md index e215bc4c..0a7fac56 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,4 +1,5 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +This is a [Next.js](https://nextjs.org) project bootstrapped with +[`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started @@ -14,23 +15,35 @@ pnpm dev bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +Open [http://localhost:3000](http://localhost:3000) with your browser to see the +result. -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +You can start editing the page by modifying `app/page.tsx`. The page +auto-updates as you edit the file. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +This project uses +[`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) +to automatically optimize and load [Geist](https://vercel.com/font), a new font +family for Vercel. ## Learn More To learn more about Next.js, take a look at the following resources: -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js + features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +You can check out +[the Next.js GitHub repository](https://github.com/vercel/next.js) - your +feedback and contributions are welcome! ## Deploy on Vercel -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +The easiest way to deploy your Next.js app is to use the +[Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) +from the creators of Next.js. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +Check out our +[Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) +for more details. diff --git a/frontend/actions/quiz.ts b/frontend/actions/quiz.ts index 85724b50..58ef6432 100644 --- a/frontend/actions/quiz.ts +++ b/frontend/actions/quiz.ts @@ -1,15 +1,16 @@ 'use server'; +import { eq, inArray } from 'drizzle-orm'; + import { db } from '@/db'; +import { awardQuizPoints, calculateQuizPoints } from '@/db/queries/points'; import { - quizAttempts, - quizAttemptAnswers, quizAnswers, + quizAttemptAnswers, + quizAttempts, quizQuestions, } from '@/db/schema/quiz'; -import { awardQuizPoints,calculateQuizPoints } from '@/db/queries/points'; import { getCurrentUser } from '@/lib/auth'; -import { eq, inArray, and } from 'drizzle-orm'; export interface UserAnswer { questionId: string; @@ -93,7 +94,8 @@ export async function submitQuizAttempt( return { success: false, error: 'Unauthorized' }; } - const { userId, quizId, answers, violations, startedAt, completedAt } = input; + const { userId, quizId, answers, violations, startedAt, completedAt } = + input; if (userId && userId !== session.id) { return { success: false, error: 'User mismatch' }; @@ -186,9 +188,10 @@ export async function submitQuizAttempt( }; } - const percentage = ((correctAnswersCount / questionIds.length) * 100).toFixed( - 2 - ); + const percentage = ( + (correctAnswersCount / questionIds.length) * + 100 + ).toFixed(2); const integrityScore = calculateIntegrityScore(violations); const timeSpentSeconds = Math.floor( (completedAtDate.getTime() - startedAtDate.getTime()) / 1000 @@ -252,3 +255,22 @@ export async function submitQuizAttempt( }; } } + +export async function initializeQuizCache( + quizId: string +): Promise<{ success: boolean; error?: string }> { + try { + const { getOrCreateQuizAnswersCache } = + await import('@/lib/quiz/quiz-answers-redis'); + const success = await getOrCreateQuizAnswersCache(quizId); + + if (!success) { + return { success: false, error: 'Quiz not found' }; + } + + return { success: true }; + } catch (error) { + console.error('Failed to initialize quiz cache:', error); + return { success: false, error: 'Internal server error' }; + } +} diff --git a/frontend/app/[locale]/about/page.tsx b/frontend/app/[locale]/about/page.tsx index 57c93a75..e4313412 100644 --- a/frontend/app/[locale]/about/page.tsx +++ b/frontend/app/[locale]/about/page.tsx @@ -1,38 +1,34 @@ -import { getTranslations } from "next-intl/server" -import { getPlatformStats } from "@/lib/about/stats" -import { getSponsors } from "@/lib/about/github-sponsors" +import { getTranslations } from 'next-intl/server'; -import { HeroSection } from "@/components/about/HeroSection" -import { TopicsSection } from "@/components/about/TopicsSection" -import { FeaturesSection } from "@/components/about/FeaturesSection" -import { PricingSection } from "@/components/about/PricingSection" -import { CommunitySection } from "@/components/about/CommunitySection" +import { CommunitySection } from '@/components/about/CommunitySection'; +import { FeaturesSection } from '@/components/about/FeaturesSection'; +import { HeroSection } from '@/components/about/HeroSection'; +import { PricingSection } from '@/components/about/PricingSection'; +import { TopicsSection } from '@/components/about/TopicsSection'; +import { getSponsors } from '@/lib/about/github-sponsors'; +import { getPlatformStats } from '@/lib/about/stats'; export async function generateMetadata() { - const t = await getTranslations("about") + const t = await getTranslations('about'); return { - title: t("metaTitle"), - description: t("metaDescription"), - } + title: t('metaTitle'), + description: t('metaDescription'), + }; } export default async function AboutPage() { const [stats, sponsors] = await Promise.all([ getPlatformStats(), - getSponsors() - ]) + getSponsors(), + ]); return ( -
- +
-
- ) -} \ No newline at end of file + ); +} diff --git a/frontend/app/[locale]/blog/[slug]/PostDetails.tsx b/frontend/app/[locale]/blog/[slug]/PostDetails.tsx index 7ce07d19..f16b593a 100644 --- a/frontend/app/[locale]/blog/[slug]/PostDetails.tsx +++ b/frontend/app/[locale]/blog/[slug]/PostDetails.tsx @@ -1,11 +1,12 @@ +import groq from 'groq'; import Image from 'next/image'; import { notFound } from 'next/navigation'; -import groq from 'groq'; import { getTranslations } from 'next-intl/server'; + import { client } from '@/client'; +import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground'; import { Link } from '@/i18n/routing'; import { formatBlogDate } from '@/lib/blog/date'; -import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground'; export const revalidate = 0; @@ -189,7 +190,7 @@ function renderPortableTextBlock(block: any, index: number): React.ReactNode { return (
{children}
@@ -209,7 +210,7 @@ function renderPortableTextBlock(block: any, index: number): React.ReactNode { return (

{children}

@@ -283,7 +284,7 @@ function renderPortableText( key={block._key || `image-${i}`} src={block.url} alt={postTitle || 'Post image'} - className="rounded-xl border border-gray-200 my-6" + className="my-6 rounded-xl border border-gray-200" /> ); i += 1; @@ -482,7 +483,7 @@ export default async function PostDetails({ : null; return ( - +
{breadcrumbsJsonLd && (