diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 58f51328..e9bd392c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -81,20 +81,20 @@ model Book { /// [BookVersion] versions Json[] - /// [BookFlags] - flags Json @default("{}") numberOfVersions Int @default(0) /// [BookExtraProperties] extraProperties Json @default("{}") + /// [BookPhysicalDetails] + physicalDetails Json? + genres Genre[] advancedGenres AdvancedGenre[] author Author @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade) authorId String - physicalDetails String? - coverImageUrl String? + coverImageUrl String? createdAt DateTime @default(now()) updatedAt DateTime? @updatedAt diff --git a/src/app/[locale]/t/[bookId]/_components/ai-tab/index.tsx b/src/app/[locale]/t/[bookId]/_components/ai-tab/index.tsx index 06aa3d89..523105ce 100644 --- a/src/app/[locale]/t/[bookId]/_components/ai-tab/index.tsx +++ b/src/app/[locale]/t/[bookId]/_components/ai-tab/index.tsx @@ -53,14 +53,14 @@ export default function AITab({ bookSlug, bookResponse }: TabProps) { const isLoading = isPending; const isVersionMismatch = - bookResponse.book.flags.aiVersion !== bookResponse.content.versionId; + bookResponse.book.aiVersion !== bookResponse.content.versionId; return (
{isVersionMismatch && ( diff --git a/src/app/[locale]/t/[bookId]/_components/search-tab/index.tsx b/src/app/[locale]/t/[bookId]/_components/search-tab/index.tsx index 18e1130a..81f63679 100644 --- a/src/app/[locale]/t/[bookId]/_components/search-tab/index.tsx +++ b/src/app/[locale]/t/[bookId]/_components/search-tab/index.tsx @@ -36,7 +36,7 @@ export default function SearchTab({ bookSlug, bookResponse }: TabProps) { const { value, setValue, results, setResults } = useSearchStore(); const isVersionMismatch = - bookResponse.book.flags.aiVersion !== bookResponse.content.versionId; + bookResponse.book.aiVersion !== bookResponse.content.versionId; const { mutateAsync, isPending, error } = useMutation< SemanticSearchBookNode[], @@ -120,7 +120,7 @@ export default function SearchTab({ bookSlug, bookResponse }: TabProps) { {isVersionMismatch && ( diff --git a/src/app/[locale]/t/[bookId]/_components/tab-content.tsx b/src/app/[locale]/t/[bookId]/_components/tab-content.tsx index aeadbfe5..97a4d80c 100644 --- a/src/app/[locale]/t/[bookId]/_components/tab-content.tsx +++ b/src/app/[locale]/t/[bookId]/_components/tab-content.tsx @@ -10,7 +10,7 @@ export const TabContent = ({ }: TabProps & { tabId: keyof typeof tabIdToComponent; }) => { - const isSupported = props.bookResponse.book.flags.aiSupported; + const isSupported = props.bookResponse.book.aiSupported; if ( (props.bookResponse.content.source === "external" || !isSupported) && diff --git a/src/data/popular-books.ts b/src/data/popular-books.ts index 6b153695..cfb75a3d 100644 --- a/src/data/popular-books.ts +++ b/src/data/popular-books.ts @@ -3,54 +3,54 @@ import { db } from "@/server/db"; import { getLocaleWhereClause } from "@/server/db/localization"; export const popularBooks = [ - { slug: "sahih" }, - { slug: "sahih-1" }, - { slug: "sunan-4" }, - { slug: "sunan-3" }, - { slug: "sahih-wa-dacif-sunan-tirmidhi" }, - { slug: "sunan-sughra" }, - { slug: "muwatta" }, - { slug: "riyad-salihin" }, - { slug: "ihya-culum-din" }, - { slug: "tafsir-jalalayn" }, - { slug: "tafsir-quran-6" }, - { slug: "fath-bari" }, + { id: "0256Bukhari.Sahih" }, + { id: "0261Muslim.Sahih" }, + { id: "0275AbuDawudSijistani.Sunan" }, + { id: "0273IbnMaja.Sunan" }, + { id: "0303Nasai.SunanSughra" }, + { id: "1420MuhammadNasirDinAlbani.SahihWaDacifSunanTirmidhi" }, + { id: "0179MalikIbnAnas.Muwatta" }, + { id: "0676Nawawi.RiyadSalihin" }, + { id: "0505Ghazali.IhyaCulumDin" }, + { id: "0911Suyuti.TafsirJalalayn" }, + { id: "0774IbnKathir.TafsirQuran" }, + { id: "0852IbnHajarCasqalani.FathBari" }, ]; export const popularIslamicLawBooks = [ - { slug: "muwatta" }, - { slug: "mughni" }, - { slug: "hidaya-fi-sharh-bidaya" }, - { slug: "bidayat-mujtahid" }, - { slug: "umm" }, - { slug: "mukhtasar-4" }, - { slug: "risala" }, - { slug: "mukhtasar-sahih-bukhari" }, - { slug: "mabsut-1" }, - { slug: "radd-muhtar" }, - { slug: "muhalla-bi-athar" }, + { id: "0179MalikIbnAnas.Muwatta" }, + { id: "0620IbnQudamaMaqdisi.Mughni" }, + { id: "0593BurhanDinFarghaniMarghinani.HidayaFiSharhBidaya" }, + { id: "0595IbnRushdHafid.BidayatMujtahid" }, + { id: "0204Shafici.Umm" }, + { id: "0428AbuHusaynQuduri.Mukhtasar" }, + { id: "0204Shafici.Risala" }, + { id: "0695IbnAbiJamra.MukhtasarSahihBukhari" }, + { id: "0483IbnAhmadSarakhsi.Mabsut" }, + { id: "1252IbnCabidinDimashqi.RaddMuhtar" }, + { id: "0456IbnHazm.MuhallaBiAthar" }, ]; export const popularIslamicHistoryBooks = [ - { slug: "sira-nabawiyya" }, - { slug: "sira" }, - { slug: "zad-macad" }, - { slug: "bidaya-1" }, - { slug: "tarikh-5" }, - { slug: "fadail-sahaba" }, - { slug: "sira-1" }, - { slug: "wafat" }, - { slug: "jawamic-sira" }, - { slug: "qisas-anbiya-1" }, + { id: "0213IbnHisham.SiraNabawiyya" }, + { id: "0151IbnIshaq.Sira" }, + { id: "0751IbnQayyimJawziyya.ZadMacad" }, + { id: "0774IbnKathir.Bidaya" }, + { id: "0310Tabari.Tarikh" }, + { id: "0241IbnHanbal.FadailSahaba" }, + { id: "0354IbnHibbanBusti.Sira" }, + { id: "0303Nasai.Wafat" }, + { id: "0456IbnHazm.JawamicSira" }, + { id: "0774IbnKathir.QisasAnbiya" }, ]; -const fetchBooksBySlugs = (slugs: string[], locale: PathLocale) => { +const fetchBooksByIds = async (ids: string[], locale: PathLocale) => { const localeWhere = getLocaleWhereClause(locale); - return db.book.findMany({ + const books = await db.book.findMany({ where: { - slug: { - in: slugs, + id: { + in: ids, }, }, include: { @@ -67,25 +67,32 @@ const fetchBooksBySlugs = (slugs: string[], locale: PathLocale) => { }, }, }); + + // Order books by their index in the ids array to maintain specified order + return books.sort((a, b) => { + const aIndex = ids.indexOf(a.id); + const bIndex = ids.indexOf(b.id); + return aIndex - bIndex; + }); }; export const fetchPopularBooks = async (locale: PathLocale) => { - return fetchBooksBySlugs( - popularBooks.map((s) => s.slug), + return fetchBooksByIds( + popularBooks.map((s) => s.id), locale, ); }; export const fetchPopularIslamicLawBooks = async (locale: PathLocale) => { - return fetchBooksBySlugs( - popularIslamicLawBooks.map((b) => b.slug), + return fetchBooksByIds( + popularIslamicLawBooks.map((b) => b.id), locale, ); }; export const fetchPopularIslamicHistoryBooks = async (locale: PathLocale) => { - return fetchBooksBySlugs( - popularIslamicHistoryBooks.map((b) => b.slug), + return fetchBooksByIds( + popularIslamicHistoryBooks.map((b) => b.id), locale, ); }; diff --git a/src/lib/seo.ts b/src/lib/seo.ts index 464f7d0e..c09bb2b0 100644 --- a/src/lib/seo.ts +++ b/src/lib/seo.ts @@ -72,11 +72,12 @@ export const getMetadata = async ({ ...newDescription, keywords, authors, + openGraph: { type: "website", siteName, url: "/", - locale, + locale: locale ?? "en_US", ...newTitle, ...newDescription, ...newImages, @@ -117,7 +118,7 @@ export const getMetadata = async ({ siteName, url: "/", title, - locale, + locale: locale ?? "en_US", description: description ?? defaultDescription, images, }, diff --git a/src/types/ApiBookResponse.ts b/src/types/ApiBookResponse.ts index da6509aa..94aecbc6 100644 --- a/src/types/ApiBookResponse.ts +++ b/src/types/ApiBookResponse.ts @@ -63,9 +63,10 @@ type BookDetails = { bio: string; }; transliteration: string; + aiSupported: boolean; + aiVersion: string; versions: PrismaJson.BookVersion[]; numberOfVersions: number; - flags: PrismaJson.BookFlags; primaryName: string; otherNames: string[]; secondaryName?: string | null; diff --git a/src/types/index.ts b/src/types/index.ts index df688690..5c4589b4 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,30 +1,51 @@ +interface PublicationDetails { + investigator?: string; + publisher?: string; + publisherLocation?: string; + editionNumber?: string; + publicationYear?: number; // hijri +} + +type SplitsData = { start: number; end: number }[]; + declare global { namespace PrismaJson { - interface BookVersion { - source: "openiti" | "turath" | "external" | "pdf"; + type BookVersion = ( + | { + source: "openiti" | "turath" | "external"; + } + | { + source: "pdf"; + ocrBookId?: string; + splitsData?: SplitsData; + } + ) & { + id: string; value: string; - publicationDetails?: { - investigator?: string; - publisher?: string; - editionNumber?: string; - publicationYear?: number; // hijri - }; - } - - interface BookFlags { + publicationDetails?: PublicationDetails; aiSupported?: boolean; - aiVersion?: string; - } + keywordSupported?: boolean; + }; interface AuthorExtraProperties { _airtableReference?: string; } interface BookExtraProperties { - splitsData?: { start: number; end: number }[]; _airtableReference?: string; } + type BookPhysicalDetails = ( + | { + type: "manuscript"; + } + | ({ + type: "published"; + } & PublicationDetails) + ) & { + notes?: string; + }; + interface GenreExtraProperties { _airtableReference?: string; }