import { format } from "date-fns"; import Head from "next/head"; import React, { useCallback, useEffect, useState } from "react"; import useSWRImmutable from "swr/immutable"; import { useAppDispatch, useAppSelector } from "../lib/hooks"; import CellList from "./CellList"; import styles from "../styles/ModData.module.css"; import { jsonFetcher } from "../lib/api"; import { PluginsByHashWithMods, removeFetchedPlugin, updateFetchedPlugin, } from "../slices/plugins"; import Link from "next/link"; export interface CellCoord { x: number; y: number; } export interface ModFile { name: string; version: string; category: string; nexus_file_id: number; } export interface FilePlugin { hash: number; file_path: string; } export interface FileCell { x: number; y: number; } export interface File { id: number; name: string; file_name: string; nexus_file_id: number; mod_id: number; category: string; version: string; mod_version: string; size: number; uploaded_at: string; created_at: string; downloaded_at: string; has_plugin: boolean; unable_to_extract_plugins: boolean; cells: FileCell[]; plugins: FilePlugin[]; plugin_count: number; } export interface Mod { id: number; name: string; nexus_mod_id: number; author_name: string; author_id: number; category_name: string; category_id: number; description: string; thumbnail_link: string; game_id: number; is_translation: boolean; updated_at: string; created_at: string; last_update_at: string; first_upload_at: string; last_updated_files_at: string; cells: CellCoord[]; files: ModFile[]; } export const NEXUS_MODS_URL = "https://www.nexusmods.com/skyrimspecialedition"; type Props = { selectedMod: number; selectedFile: number; selectedPlugin: string; counts: Record | null; setSelectedCells: (cells: { x: number; y: number }[] | null) => void; onSelectFile: (fileId: number) => void; onSelectPlugin: (hash: string) => void; }; const ModData: React.FC = ({ selectedMod, selectedFile, selectedPlugin, counts, setSelectedCells, onSelectFile, onSelectPlugin, }) => { const { data: modData, error: modError } = useSWRImmutable( `https://mods.modmapper.com/${selectedMod}.json`, (_) => jsonFetcher(_) ); const { data: fileData, error: fileError } = useSWRImmutable( selectedFile ? `https://files.modmapper.com/${selectedFile}.json` : null, (_) => jsonFetcher(_) ); const { data: pluginData, error: pluginError } = useSWRImmutable( selectedPlugin ? `https://plugins.modmapper.com/${selectedPlugin}.json` : null, (_) => jsonFetcher(_) ); const dispatch = useAppDispatch(); const fetchedPlugin = useAppSelector((state) => state.plugins.fetchedPlugins.find( (plugin) => plugin.hash === selectedPlugin ) ); const handleFileChange = useCallback( (event) => { onSelectFile(event.target.value); }, [onSelectFile] ); const handlePluginChange = useCallback( (event) => { onSelectPlugin(event.target.value); }, [onSelectPlugin] ); useEffect(() => { if (modData && !selectedFile) setSelectedCells(modData.cells); }, [modData, setSelectedCells, selectedFile]); useEffect(() => { if (fileData) setSelectedCells(fileData.cells); }, [fileData, setSelectedCells]); if (modError && modError.status === 404) { return
Mod could not be found.
; } else if (modError) { return
{`Error loading mod modData: ${modError.message}`}
; } if (modData === undefined) return
Loading...
; if (modData === null) return
Mod could not be found.
; let numberFmt = new Intl.NumberFormat("en-US"); const modCounts = counts && counts[modData.nexus_mod_id]; const total_downloads = modCounts ? modCounts[0] : 0; const unique_downloads = modCounts ? modCounts[1] : 0; const views = modCounts ? modCounts[2] : 0; if (selectedMod && modData) { return ( <> {`Modmapper - ${modData.name}`}

{modData.name}

Category:  {modData.category_name} {modData.is_translation &&  (translation)}
Uploaded:{" "} {format(new Date(modData.first_upload_at), "d MMM y")}
Last Update:{" "} {format(new Date(modData.last_update_at), "d MMM y")}
Total Downloads: {numberFmt.format(total_downloads)}
Unique Downloads:{" "} {numberFmt.format(unique_downloads)}
{fileData && (
)} {pluginData ? (
View plugin
) : (
)} {fileError && (fileError.status === 404 ? (
File cound not be found.
) : (
{`Error loading file data: ${fileError.message}`}
))} {pluginError && (pluginError.status === 404 ? (
Plugin cound not be found.
) : (
{`Error loading plugin data: ${pluginError.message}`}
))} ); } return null; }; export default ModData;