diff --git a/biome.json b/biome.json index be9b94f..2b9b070 100644 --- a/biome.json +++ b/biome.json @@ -66,6 +66,8 @@ "src/components/magicui/*.tsx", "src/app/[[]locale]/preview/**", "src/db/schema.ts", + "src/payment/types.ts", + "src/types/index.d.ts", "public/sw.js" ] }, @@ -76,4 +78,4 @@ "semicolons": "always" } } -} +} \ No newline at end of file diff --git a/content-collections.ts b/content-collections.ts index a549add..f283c77 100644 --- a/content-collections.ts +++ b/content-collections.ts @@ -1,18 +1,18 @@ -import { DEFAULT_LOCALE, LOCALES } from "@/i18n/routing"; -import { defineCollection, defineConfig } from "@content-collections/core"; +import path from 'path'; +import { DEFAULT_LOCALE, LOCALES } from '@/i18n/routing'; +import { defineCollection, defineConfig } from '@content-collections/core'; import { createDocSchema, createMetaSchema, transformMDX, } from '@fumadocs/content-collections/configuration'; -import path from "path"; /** * 1. Content Collections documentation * https://www.content-collections.dev/docs/quickstart/next * https://www.content-collections.dev/docs/configuration * https://www.content-collections.dev/docs/transform#join-collections - * + * * 2. Use Content Collections for Fumadocs * https://fumadocs.vercel.app/docs/headless/content-collections */ @@ -38,11 +38,11 @@ const metas = defineCollection({ /** * Blog Author collection - * + * * Authors are identified by their slug across all languages * New format: content/author/authorname.{locale}.mdx * Example: content/author/mksaas.mdx (default locale) and content/author/mksaas.zh.mdx (Chinese) - * + * * For author, slug is slugAsParams */ export const authors = defineCollection({ @@ -53,7 +53,7 @@ export const authors = defineCollection({ slug: z.string(), name: z.string(), avatar: z.string(), - locale: z.string().optional().default(DEFAULT_LOCALE) + locale: z.string().optional().default(DEFAULT_LOCALE), }), transform: async (data, context) => { // Get the filename from the path @@ -68,16 +68,16 @@ export const authors = defineCollection({ ...data, locale, }; - } + }, }); /** * Blog Category collection - * + * * Categories are identified by their slug across all languages * New format: content/category/categoryname.{locale}.mdx * Example: content/category/tutorial.mdx (default locale) and content/category/tutorial.zh.mdx (Chinese) - * + * * For category, slug is slugAsParams */ export const categories = defineCollection({ @@ -88,7 +88,7 @@ export const categories = defineCollection({ slug: z.string(), name: z.string(), description: z.string(), - locale: z.string().optional().default(DEFAULT_LOCALE) + locale: z.string().optional().default(DEFAULT_LOCALE), }), transform: async (data, context) => { // Get the filename from the path @@ -101,24 +101,24 @@ export const categories = defineCollection({ return { ...data, - locale + locale, }; - } + }, }); /** * Blog Post collection - * + * * New format: content/blog/post-slug.{locale}.mdx - * + * * slug: /blog/first-post, used in URL or sitemap * slugAsParams: first-post, used in route params - * + * * 1. For a blog post at content/blog/first-post.mdx (default locale): * locale: en * slug: /blog/first-post * slugAsParams: first-post - * + * * 2. For a blog post at content/blog/first-post.zh.mdx (Chinese locale): * locale: zh * slug: /blog/first-post @@ -136,7 +136,7 @@ export const posts = defineCollection({ published: z.boolean().default(true), categories: z.array(z.string()), author: z.string(), - estimatedTime: z.number().optional() // Reading time in minutes + estimatedTime: z.number().optional(), // Reading time in minutes }), transform: async (data, context) => { // Use Fumadocs transformMDX for consistent MDX processing @@ -156,18 +156,20 @@ export const posts = defineCollection({ .find((a) => a.slug === data.author && a.locale === locale); // Find categories by matching slug and locale - const blogCategories = data.categories.map(categorySlug => { - const category = context - .documents(categories) - .find(c => c.slug === categorySlug && c.locale === locale); + const blogCategories = data.categories + .map((categorySlug) => { + const category = context + .documents(categories) + .find((c) => c.slug === categorySlug && c.locale === locale); - return category; - }).filter(Boolean); // Remove null values + return category; + }) + .filter(Boolean); // Remove null values // Create the slug and slugAsParams const slug = `/blog/${base}`; const slugAsParams = base; - + // Calculate estimated reading time const wordCount = data.content.split(/\s+/).length; const wordsPerMinute = 200; // average reading speed: 200 words per minute @@ -182,21 +184,21 @@ export const posts = defineCollection({ slugAsParams, estimatedTime, body: transformedData.body, - toc: transformedData.toc + toc: transformedData.toc, }; - } + }, }); /** * Pages collection for policy pages like privacy-policy, terms-of-service, etc. - * + * * New format: content/pages/page-slug.{locale}.mdx - * + * * 1. For a page at content/pages/privacy-policy.mdx (default locale): * locale: en * slug: /pages/privacy-policy * slugAsParams: privacy-policy - * + * * 2. For a page at content/pages/privacy-policy.zh.mdx (Chinese locale): * locale: zh * slug: /pages/privacy-policy @@ -210,7 +212,7 @@ export const pages = defineCollection({ title: z.string(), description: z.string(), date: z.string().datetime(), - published: z.boolean().default(true) + published: z.boolean().default(true), }), transform: async (data, context) => { // Use Fumadocs transformMDX for consistent MDX processing @@ -234,21 +236,21 @@ export const pages = defineCollection({ slug, slugAsParams, body: transformedData.body, - toc: transformedData.toc + toc: transformedData.toc, }; - } + }, }); /** * Releases collection for changelog - * + * * New format: content/release/version-slug.{locale}.mdx - * + * * 1. For a release at content/release/v1-0-0.mdx (default locale): * locale: en * slug: /release/v1-0-0 * slugAsParams: v1-0-0 - * + * * 2. For a release at content/release/v1-0-0.zh.mdx (Chinese locale): * locale: zh * slug: /release/v1-0-0 @@ -263,7 +265,7 @@ export const releases = defineCollection({ description: z.string(), date: z.string().datetime(), version: z.string(), - published: z.boolean().default(true) + published: z.boolean().default(true), }), transform: async (data, context) => { // Use Fumadocs transformMDX for consistent MDX processing @@ -287,9 +289,9 @@ export const releases = defineCollection({ slug, slugAsParams, body: transformedData.body, - toc: transformedData.toc + toc: transformedData.toc, }; - } + }, }); /** @@ -297,11 +299,14 @@ export const releases = defineCollection({ * Handles filename formats: * - name -> locale: DEFAULT_LOCALE, base: name * - name.zh -> locale: zh, base: name - * + * * @param fileName Filename without extension (already has .mdx removed) * @returns Object with locale and base name */ -function extractLocaleAndBase(fileName: string): { locale: string; base: string } { +function extractLocaleAndBase(fileName: string): { + locale: string; + base: string; +} { // Split filename into parts const parts = fileName.split('.'); @@ -319,5 +324,5 @@ function extractLocaleAndBase(fileName: string): { locale: string; base: string } export default defineConfig({ - collections: [docs, metas, authors, categories, posts, pages, releases] -}); \ No newline at end of file + collections: [docs, metas, authors, categories, posts, pages, releases], +}); diff --git a/global.d.ts b/global.d.ts index 7479cfd..da0d666 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,9 +1,9 @@ -import { routing } from '@/i18n/routing'; -import messages from './messages/en.json'; +import type { routing } from '@/i18n/routing'; +import type messages from './messages/en.json'; /** * next-intl 4.0.0 - * + * * https://github.com/amannn/next-intl/blob/main/examples/example-app-router/global.d.ts */ declare module 'next-intl' { diff --git a/messages/en.json b/messages/en.json index 4072a2d..993b129 100644 --- a/messages/en.json +++ b/messages/en.json @@ -848,4 +848,4 @@ "description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly", "content": "Working in progress" } -} \ No newline at end of file +} diff --git a/messages/zh.json b/messages/zh.json index 42b0724..e3071cd 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -671,7 +671,7 @@ }, "item-2": { "title": "产品特色功能二", - "description": "请在这里详细描述您的产品特色功能二,尽可能详细,使其更吸引用户" + "description": "请在这里详细描述您的产品特色功能二,尽可能详细,使其更吸引用户" }, "item-3": { "title": "产品特色功能三", @@ -849,4 +849,4 @@ "description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力", "content": "正在开发中" } -} \ No newline at end of file +} diff --git a/next.config.ts b/next.config.ts index f66e975..56799cc 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,6 +1,6 @@ -import type { NextConfig } from "next"; +import { withContentCollections } from '@content-collections/next'; +import type { NextConfig } from 'next'; import createNextIntlPlugin from 'next-intl/plugin'; -import { withContentCollections } from "@content-collections/next"; /** * https://nextjs.org/docs/app/api-reference/config/next-config-js @@ -12,22 +12,22 @@ const nextConfig: NextConfig = { // https://nextjs.org/docs/architecture/nextjs-compiler#remove-console // Remove all console.* calls in production only compiler: { - removeConsole: process.env.NODE_ENV === "production", + removeConsole: process.env.NODE_ENV === 'production', }, images: { remotePatterns: [ { - protocol: "https", - hostname: "avatars.githubusercontent.com", + protocol: 'https', + hostname: 'avatars.githubusercontent.com', }, { - protocol: "https", - hostname: "lh3.googleusercontent.com", + protocol: 'https', + hostname: 'lh3.googleusercontent.com', }, { - protocol: "https", - hostname: "randomuser.me", + protocol: 'https', + hostname: 'randomuser.me', }, { protocol: 'https', @@ -39,14 +39,14 @@ const nextConfig: NextConfig = { /** * You can specify the path to the request config file or use the default one (@/i18n/request.ts) - * + * * https://next-intl.dev/docs/getting-started/app-router/with-i18n-routing#next-config */ const withNextIntl = createNextIntlPlugin(); /** * withContentCollections must be the outermost plugin - * + * * https://www.content-collections.dev/docs/quickstart/next */ export default withContentCollections(withNextIntl(nextConfig)); diff --git a/src/actions/check-newsletter-status.ts b/src/actions/check-newsletter-status.ts index bdcba14..2daca00 100644 --- a/src/actions/check-newsletter-status.ts +++ b/src/actions/check-newsletter-status.ts @@ -31,4 +31,4 @@ export const checkNewsletterStatusAction = actionClient error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/create-checkout-session.ts b/src/actions/create-checkout-session.ts index 327f021..7a52ae6 100644 --- a/src/actions/create-checkout-session.ts +++ b/src/actions/create-checkout-session.ts @@ -1,14 +1,14 @@ 'use server'; -import { getSession } from "@/lib/server"; -import { findPlanByPlanId } from "@/lib/price-plan"; -import { getUrlWithLocale } from "@/lib/urls/urls"; -import { createCheckout } from "@/payment"; -import { CreateCheckoutParams } from "@/payment/types"; -import { getLocale } from "next-intl/server"; +import { findPlanByPlanId } from '@/lib/price-plan'; +import { getSession } from '@/lib/server'; +import { getUrlWithLocale } from '@/lib/urls/urls'; +import { createCheckout } from '@/payment'; +import type { CreateCheckoutParams } from '@/payment/types'; +import { Routes } from '@/routes'; +import { getLocale } from 'next-intl/server'; import { createSafeActionClient } from 'next-safe-action'; import { z } from 'zod'; -import { Routes } from "@/routes"; // Create a safe action client const actionClient = createSafeActionClient(); @@ -33,7 +33,9 @@ export const createCheckoutAction = actionClient // Get the current user session for authorization const session = await getSession(); if (!session) { - console.warn(`unauthorized request to create checkout session for user ${userId}`); + console.warn( + `unauthorized request to create checkout session for user ${userId}` + ); return { success: false, error: 'Unauthorized', @@ -42,7 +44,9 @@ export const createCheckoutAction = actionClient // Only allow users to create their own checkout session if (session.user.id !== userId) { - console.warn(`current user ${session.user.id} is not authorized to create checkout session for user ${userId}`); + console.warn( + `current user ${session.user.id} is not authorized to create checkout session for user ${userId}` + ); return { success: false, error: 'Not authorized to do this action', @@ -70,7 +74,10 @@ export const createCheckoutAction = actionClient }; // Create the checkout session with localized URLs - const successUrl = getUrlWithLocale('/settings/billing?session_id={CHECKOUT_SESSION_ID}', locale); + const successUrl = getUrlWithLocale( + '/settings/billing?session_id={CHECKOUT_SESSION_ID}', + locale + ); const cancelUrl = getUrlWithLocale(Routes.Pricing, locale); const params: CreateCheckoutParams = { planId, @@ -89,10 +96,10 @@ export const createCheckoutAction = actionClient data: result, }; } catch (error) { - console.error("create checkout session error:", error); + console.error('create checkout session error:', error); return { success: false, error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/create-customer-portal-session.ts b/src/actions/create-customer-portal-session.ts index f7cdec0..e4e46fa 100644 --- a/src/actions/create-customer-portal-session.ts +++ b/src/actions/create-customer-portal-session.ts @@ -1,13 +1,13 @@ 'use server'; -import db from "@/db"; -import { user } from "@/db/schema"; -import { getSession } from "@/lib/server"; -import { getUrlWithLocale } from "@/lib/urls/urls"; -import { createCustomerPortal } from "@/payment"; -import { CreatePortalParams } from "@/payment/types"; -import { eq } from "drizzle-orm"; -import { getLocale } from "next-intl/server"; +import db from '@/db'; +import { user } from '@/db/schema'; +import { getSession } from '@/lib/server'; +import { getUrlWithLocale } from '@/lib/urls/urls'; +import { createCustomerPortal } from '@/payment'; +import type { CreatePortalParams } from '@/payment/types'; +import { eq } from 'drizzle-orm'; +import { getLocale } from 'next-intl/server'; import { createSafeActionClient } from 'next-safe-action'; import { z } from 'zod'; @@ -17,7 +17,10 @@ const actionClient = createSafeActionClient(); // Portal schema for validation const portalSchema = z.object({ userId: z.string().min(1, { message: 'User ID is required' }), - returnUrl: z.string().url({ message: 'Return URL must be a valid URL' }).optional(), + returnUrl: z + .string() + .url({ message: 'Return URL must be a valid URL' }) + .optional(), }); /** @@ -27,11 +30,13 @@ export const createPortalAction = actionClient .schema(portalSchema) .action(async ({ parsedInput }) => { const { userId, returnUrl } = parsedInput; - + // Get the current user session for authorization const session = await getSession(); if (!session) { - console.warn(`unauthorized request to create portal session for user ${userId}`); + console.warn( + `unauthorized request to create portal session for user ${userId}` + ); return { success: false, error: 'Unauthorized', @@ -40,7 +45,9 @@ export const createPortalAction = actionClient // Only allow users to create their own portal session if (session.user.id !== userId) { - console.warn(`current user ${session.user.id} is not authorized to create portal session for user ${userId}`); + console.warn( + `current user ${session.user.id} is not authorized to create portal session for user ${userId}` + ); return { success: false, error: 'Not authorized to do this action', @@ -67,11 +74,12 @@ export const createPortalAction = actionClient const locale = await getLocale(); // Create the portal session with localized URL if no custom return URL is provided - const returnUrlWithLocale = returnUrl || getUrlWithLocale('/settings/billing', locale); + const returnUrlWithLocale = + returnUrl || getUrlWithLocale('/settings/billing', locale); const params: CreatePortalParams = { customerId: customerResult[0].customerId, returnUrl: returnUrlWithLocale, - locale + locale, }; const result = await createCustomerPortal(params); @@ -81,10 +89,10 @@ export const createPortalAction = actionClient data: result, }; } catch (error) { - console.error("create customer portal error:", error); + console.error('create customer portal error:', error); return { success: false, error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/get-active-subscription.ts b/src/actions/get-active-subscription.ts index f98c912..ecab486 100644 --- a/src/actions/get-active-subscription.ts +++ b/src/actions/get-active-subscription.ts @@ -1,9 +1,9 @@ 'use server'; -import { getSession } from "@/lib/server"; -import { getSubscriptions } from "@/payment"; +import { getSession } from '@/lib/server'; +import { getSubscriptions } from '@/payment'; import { createSafeActionClient } from 'next-safe-action'; -import { z } from "zod"; +import { z } from 'zod'; // Create a safe action client const actionClient = createSafeActionClient(); @@ -15,8 +15,8 @@ const schema = z.object({ /** * Get active subscription data - * - * If the user has multiple subscriptions, + * + * If the user has multiple subscriptions, * it returns the most recent active or trialing one */ export const getActiveSubscriptionAction = actionClient @@ -27,7 +27,9 @@ export const getActiveSubscriptionAction = actionClient // Get the current user session for authorization const session = await getSession(); if (!session) { - console.warn(`unauthorized request to get active subscription for user ${userId}`); + console.warn( + `unauthorized request to get active subscription for user ${userId}` + ); return { success: false, error: 'Unauthorized', @@ -36,7 +38,9 @@ export const getActiveSubscriptionAction = actionClient // Only allow users to check their own status unless they're admins if (session.user.id !== userId && session.user.role !== 'admin') { - console.warn(`current user ${session.user.id} is not authorized to get active subscription for user ${userId}`); + console.warn( + `current user ${session.user.id} is not authorized to get active subscription for user ${userId}` + ); return { success: false, error: 'Not authorized to do this action', @@ -46,7 +50,7 @@ export const getActiveSubscriptionAction = actionClient try { // Find the user's most recent active subscription const subscriptions = await getSubscriptions({ - userId: session.user.id + userId: session.user.id, }); // console.log('get user subscriptions:', subscriptions); @@ -54,8 +58,8 @@ export const getActiveSubscriptionAction = actionClient // Find the most recent active subscription (if any) if (subscriptions && subscriptions.length > 0) { // First try to find an active subscription - const activeSubscription = subscriptions.find(sub => - sub.status === 'active' || sub.status === 'trialing' + const activeSubscription = subscriptions.find( + (sub) => sub.status === 'active' || sub.status === 'trialing' ); // If found, use it @@ -63,7 +67,10 @@ export const getActiveSubscriptionAction = actionClient console.log('find active subscription for userId:', session.user.id); subscriptionData = activeSubscription; } else { - console.log('no active subscription found for userId:', session.user.id); + console.log( + 'no active subscription found for userId:', + session.user.id + ); } } else { console.log('no subscriptions found for userId:', session.user.id); @@ -74,10 +81,10 @@ export const getActiveSubscriptionAction = actionClient data: subscriptionData, }; } catch (error) { - console.error("get user subscription data error:", error); + console.error('get user subscription data error:', error); return { success: false, error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/get-lifetime-status.ts b/src/actions/get-lifetime-status.ts index b4c58dc..ac98a56 100644 --- a/src/actions/get-lifetime-status.ts +++ b/src/actions/get-lifetime-status.ts @@ -1,13 +1,13 @@ 'use server'; -import db from "@/db"; -import { payment } from "@/db/schema"; -import { getSession } from "@/lib/server"; -import { getAllPricePlans, findPlanByPriceId } from "@/lib/price-plan"; -import { PaymentTypes } from "@/payment/types"; -import { and, eq } from "drizzle-orm"; +import db from '@/db'; +import { payment } from '@/db/schema'; +import { findPlanByPriceId, getAllPricePlans } from '@/lib/price-plan'; +import { getSession } from '@/lib/server'; +import { PaymentTypes } from '@/payment/types'; +import { and, eq } from 'drizzle-orm'; import { createSafeActionClient } from 'next-safe-action'; -import { z } from "zod"; +import { z } from 'zod'; // Create a safe action client const actionClient = createSafeActionClient(); @@ -19,8 +19,8 @@ const schema = z.object({ /** * Get user lifetime membership status directly from the database - * - * NOTICE: If you first add lifetime plan and then delete it, + * + * NOTICE: If you first add lifetime plan and then delete it, * the user with lifetime plan should be considered as a lifetime member as well, * in order to do this, you have to update the logic to check the lifetime status, * for example, just check the planId is `lifetime` or not. @@ -33,7 +33,9 @@ export const getLifetimeStatusAction = actionClient // Get the current user session for authorization const session = await getSession(); if (!session) { - console.warn(`unauthorized request to get lifetime status for user ${userId}`); + console.warn( + `unauthorized request to get lifetime status for user ${userId}` + ); return { success: false, error: 'Unauthorized', @@ -42,7 +44,9 @@ export const getLifetimeStatusAction = actionClient // Only allow users to check their own status unless they're admins if (session.user.id !== userId && session.user.role !== 'admin') { - console.warn(`current user ${session.user.id} is not authorized to get lifetime status for user ${userId}`); + console.warn( + `current user ${session.user.id} is not authorized to get lifetime status for user ${userId}` + ); return { success: false, error: 'Not authorized to do this action', @@ -53,8 +57,8 @@ export const getLifetimeStatusAction = actionClient // Get lifetime plans const plans = getAllPricePlans(); const lifetimePlanIds = plans - .filter(plan => plan.isLifetime) - .map(plan => plan.id); + .filter((plan) => plan.isLifetime) + .map((plan) => plan.id); // Check if there are any lifetime plans defined in the system if (lifetimePlanIds.length === 0) { @@ -66,7 +70,11 @@ export const getLifetimeStatusAction = actionClient // Query the database for one-time payments with lifetime plans const result = await db - .select({ id: payment.id, priceId: payment.priceId, type: payment.type }) + .select({ + id: payment.id, + priceId: payment.priceId, + type: payment.type, + }) .from(payment) .where( and( @@ -77,7 +85,7 @@ export const getLifetimeStatusAction = actionClient ); // Check if any payment has a lifetime plan - const hasLifetimePayment = result.some(paymentRecord => { + const hasLifetimePayment = result.some((paymentRecord) => { const plan = findPlanByPriceId(paymentRecord.priceId); return plan && lifetimePlanIds.includes(plan.id); }); @@ -87,10 +95,10 @@ export const getLifetimeStatusAction = actionClient isLifetimeMember: hasLifetimePayment, }; } catch (error) { - console.error("get user lifetime status error:", error); + console.error('get user lifetime status error:', error); return { success: false, error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/send-message.ts b/src/actions/send-message.ts index 1fb4a9b..47a2458 100644 --- a/src/actions/send-message.ts +++ b/src/actions/send-message.ts @@ -15,12 +15,13 @@ const actionClient = createSafeActionClient(); */ // Contact form schema for validation const contactFormSchema = z.object({ - name: z.string() + name: z + .string() .min(3, { message: 'Name must be at least 3 characters' }) .max(30, { message: 'Name must not exceed 30 characters' }), - email: z.string() - .email({ message: 'Please enter a valid email address' }), - message: z.string() + email: z.string().email({ message: 'Please enter a valid email address' }), + message: z + .string() .min(10, { message: 'Message must be at least 10 characters' }) .max(500, { message: 'Message must not exceed 500 characters' }), }); diff --git a/src/actions/subscribe-newsletter.ts b/src/actions/subscribe-newsletter.ts index c286e1d..3d7018a 100644 --- a/src/actions/subscribe-newsletter.ts +++ b/src/actions/subscribe-newsletter.ts @@ -51,4 +51,4 @@ export const subscribeNewsletterAction = actionClient error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/actions/unsubscribe-newsletter.ts b/src/actions/unsubscribe-newsletter.ts index e5006de..332623a 100644 --- a/src/actions/unsubscribe-newsletter.ts +++ b/src/actions/unsubscribe-newsletter.ts @@ -24,7 +24,7 @@ export const unsubscribeNewsletterAction = actionClient error: 'Unauthorized', }; } - + try { const unsubscribed = await unsubscribe(email); @@ -46,4 +46,4 @@ export const unsubscribeNewsletterAction = actionClient error: error instanceof Error ? error.message : 'Something went wrong', }; } - }); \ No newline at end of file + }); diff --git a/src/analytics/analytics.tsx b/src/analytics/analytics.tsx index 5043ff8..c4a315e 100644 --- a/src/analytics/analytics.tsx +++ b/src/analytics/analytics.tsx @@ -1,9 +1,9 @@ -import GoogleAnalytics from "./google-analytics"; -import { UmamiAnalytics } from "./umami-analytics"; -import { PlausibleAnalytics } from "./plausible-analytics"; -import DataFastAnalytics from "./data-fast-analytics"; -import OpenPanelAnalytics from "./open-panel-analytics"; -import { SelineAnalytics } from "./seline-analytics"; +import DataFastAnalytics from './data-fast-analytics'; +import GoogleAnalytics from './google-analytics'; +import OpenPanelAnalytics from './open-panel-analytics'; +import { PlausibleAnalytics } from './plausible-analytics'; +import { SelineAnalytics } from './seline-analytics'; +import { UmamiAnalytics } from './umami-analytics'; /** * Analytics Components all in one @@ -12,7 +12,7 @@ import { SelineAnalytics } from "./seline-analytics"; * 2. only work if the environment variable for the analytics is set */ export function Analytics() { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== 'production') { return null; } diff --git a/src/analytics/data-fast-analytics.tsx b/src/analytics/data-fast-analytics.tsx index 2faff5e..b39bbc1 100644 --- a/src/analytics/data-fast-analytics.tsx +++ b/src/analytics/data-fast-analytics.tsx @@ -1,6 +1,6 @@ -"use client"; +'use client'; -import Script from "next/script"; +import Script from 'next/script'; /** * DataFast Analytics @@ -8,7 +8,7 @@ import Script from "next/script"; * https://datafa.st */ export default function DataFastAnalytics() { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== 'production') { return null; } diff --git a/src/analytics/google-analytics.tsx b/src/analytics/google-analytics.tsx index 941258f..038b529 100644 --- a/src/analytics/google-analytics.tsx +++ b/src/analytics/google-analytics.tsx @@ -1,6 +1,6 @@ -"use client"; +'use client'; -import { GoogleAnalytics as NextGoogleAnalytics } from "@next/third-parties/google"; +import { GoogleAnalytics as NextGoogleAnalytics } from '@next/third-parties/google'; /** * Google Analytics @@ -9,7 +9,7 @@ import { GoogleAnalytics as NextGoogleAnalytics } from "@next/third-parties/goog * https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries#google-analytics */ export default function GoogleAnalytics() { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== 'production') { return null; } diff --git a/src/analytics/open-panel-analytics.tsx b/src/analytics/open-panel-analytics.tsx index d83f9fe..b2badf4 100644 --- a/src/analytics/open-panel-analytics.tsx +++ b/src/analytics/open-panel-analytics.tsx @@ -1,4 +1,4 @@ -import { OpenPanelComponent } from "@openpanel/nextjs"; +import { OpenPanelComponent } from '@openpanel/nextjs'; /** * OpenPanel Analytics (https://openpanel.dev) @@ -6,7 +6,7 @@ import { OpenPanelComponent } from "@openpanel/nextjs"; * https://docs.openpanel.dev/docs/sdks/nextjs#options */ export default function OpenPanelAnalytics() { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== 'production') { return null; } diff --git a/src/analytics/plausible-analytics.tsx b/src/analytics/plausible-analytics.tsx index ecfa7ff..82422b1 100644 --- a/src/analytics/plausible-analytics.tsx +++ b/src/analytics/plausible-analytics.tsx @@ -1,6 +1,6 @@ -"use client"; +'use client'; -import Script from "next/script"; +import Script from 'next/script'; /** * Plausible Analytics @@ -8,7 +8,7 @@ import Script from "next/script"; * https://plausible.io */ export function PlausibleAnalytics() { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== 'production') { return null; } @@ -23,11 +23,6 @@ export function PlausibleAnalytics() { } return ( -