UPDATE: More setting in theorycraft mode
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m4s
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m4s
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
import { EyeOff, Eye, Hammer, RefreshCw, ShieldBan, User, Swords, SkipForward, BowArrow, Info } from "lucide-react"
|
import { EyeOff, Eye, Hammer, RefreshCw, ShieldBan, User, Swords, SkipForward, BowArrow, Info, RouteIcon, Search } from "lucide-react"
|
||||||
import useGlobalStore from '@/stores/globalStore'
|
import useGlobalStore from '@/stores/globalStore'
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import useEventStore from "@/stores/eventStore"
|
import useEventStore from "@/stores/eventStore"
|
||||||
@@ -8,6 +8,8 @@ import { getLocaleName, getNameChar } from "@/helper"
|
|||||||
import useLocaleStore from "@/stores/localeStore"
|
import useLocaleStore from "@/stores/localeStore"
|
||||||
import useAvatarStore from "@/stores/avatarStore"
|
import useAvatarStore from "@/stores/avatarStore"
|
||||||
import SelectCustomImage from "../select/customSelectImage"
|
import SelectCustomImage from "../select/customSelectImage"
|
||||||
|
import { useMemo, useState } from "react"
|
||||||
|
import useMazeStore from "@/stores/mazeStore"
|
||||||
|
|
||||||
export default function ExtraSettingBar() {
|
export default function ExtraSettingBar() {
|
||||||
const { extraData, setExtraData } = useGlobalStore()
|
const { extraData, setExtraData } = useGlobalStore()
|
||||||
@@ -15,6 +17,32 @@ export default function ExtraSettingBar() {
|
|||||||
const { PEAKEvent } = useEventStore()
|
const { PEAKEvent } = useEventStore()
|
||||||
const { listAvatar } = useAvatarStore()
|
const { listAvatar } = useAvatarStore()
|
||||||
const { locale } = useLocaleStore()
|
const { locale } = useLocaleStore()
|
||||||
|
const [showSearchStage, setShowSearchStage] = useState(false)
|
||||||
|
const [isChildClick, setIsChildClick] = useState(false)
|
||||||
|
const [stageSearchTerm, setStageSearchTerm] = useState("")
|
||||||
|
const [stagePage, setStagePage] = useState(1)
|
||||||
|
const { Stage } = useMazeStore()
|
||||||
|
const pageSize = 30
|
||||||
|
const stageList = useMemo(() => Object.values(Stage).map((stage) => ({
|
||||||
|
id: stage.stage_id.toString(),
|
||||||
|
name: `${stage.stage_type} (${stage.stage_id})`,
|
||||||
|
})), [Stage])
|
||||||
|
|
||||||
|
const filteredStages = useMemo(() => stageList.filter((s) =>
|
||||||
|
s.name.toLowerCase().includes(stageSearchTerm.toLowerCase())
|
||||||
|
), [stageList, stageSearchTerm])
|
||||||
|
|
||||||
|
const paginatedStages = useMemo(() => filteredStages.slice(
|
||||||
|
(stagePage - 1) * pageSize,
|
||||||
|
stagePage * pageSize
|
||||||
|
), [filteredStages, stagePage, pageSize])
|
||||||
|
|
||||||
|
const hasMorePages = useMemo(() => stagePage * pageSize < filteredStages.length, [stagePage, filteredStages])
|
||||||
|
|
||||||
|
const onChangeSearch = (v: string) => {
|
||||||
|
setStageSearchTerm(v)
|
||||||
|
setStagePage(1)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-4 sm:px-6 py-4 space-y-8">
|
<div className="px-4 sm:px-6 py-4 space-y-8">
|
||||||
@@ -39,8 +67,9 @@ export default function ExtraSettingBar() {
|
|||||||
...extraData,
|
...extraData,
|
||||||
theory_craft: {
|
theory_craft: {
|
||||||
hp: extraData?.theory_craft?.hp || {},
|
hp: extraData?.theory_craft?.hp || {},
|
||||||
cycle_count: extraData?.theory_craft?.cycle_count || 0,
|
cycle_count: extraData?.theory_craft?.cycle_count || 1,
|
||||||
mode: e.target.checked
|
mode: e.target.checked,
|
||||||
|
stage_id: extraData?.theory_craft?.stage_id || 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,6 +81,7 @@ export default function ExtraSettingBar() {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{extraData?.theory_craft?.mode && (
|
{extraData?.theory_craft?.mode && (
|
||||||
|
<>
|
||||||
<motion.div className="form-control bg-base-200 p-4 rounded-xl shadow">
|
<motion.div className="form-control bg-base-200 p-4 rounded-xl shadow">
|
||||||
<label className="flex flex-wrap items-center justify-start gap-3">
|
<label className="flex flex-wrap items-center justify-start gap-3">
|
||||||
<RefreshCw className="text-info" size={20} />
|
<RefreshCw className="text-info" size={20} />
|
||||||
@@ -65,8 +95,9 @@ export default function ExtraSettingBar() {
|
|||||||
...extraData,
|
...extraData,
|
||||||
theory_craft: {
|
theory_craft: {
|
||||||
hp: extraData?.theory_craft?.hp || {},
|
hp: extraData?.theory_craft?.hp || {},
|
||||||
cycle_count: parseInt(e.target.value) || 1,
|
cycle_count: Number(e.target.value) || 1,
|
||||||
mode: extraData?.theory_craft?.mode || false
|
mode: extraData?.theory_craft?.mode || false,
|
||||||
|
stage_id: extraData?.theory_craft?.stage_id || 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -74,6 +105,121 @@ export default function ExtraSettingBar() {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
<motion.div className="form-control bg-base-200 p-4 rounded-xl shadow">
|
||||||
|
<label className="flex flex-wrap items-center justify-start gap-3">
|
||||||
|
<RouteIcon className="text-info" size={20} />
|
||||||
|
<span className="label-text font-semibold">{transI18n("stage")}</span>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
<button
|
||||||
|
className="btn btn-outline w-full text-left flex items-center gap-2"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
if (!isChildClick) {
|
||||||
|
setShowSearchStage(pre => !pre)
|
||||||
|
}
|
||||||
|
setIsChildClick(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Search className="w-6 h-6" />
|
||||||
|
<span className="text-left"> {transI18n("stage")}: {stageList.find((s) => s.id === extraData?.theory_craft?.stage_id?.toString())?.name || transI18n("selectStage")}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{showSearchStage && (
|
||||||
|
<div onClick={(e) => e.stopPropagation()} className="absolute top-full mt-2 w-full z-50 border bg-base-200 border-slate-600 rounded-lg p-4 shadow-lg">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
|
||||||
|
<label className="input w-full">
|
||||||
|
<svg className="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<g
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeWidth="2.5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<path d="m21 21-4.3-4.3"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
type="search" className="grow"
|
||||||
|
placeholder={transI18n("searchStage")}
|
||||||
|
value={stageSearchTerm}
|
||||||
|
onChange={(e) => onChangeSearch(e.target.value)}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-h-60 overflow-y-auto space-y-1">
|
||||||
|
{paginatedStages.length > 0 ? (
|
||||||
|
<>
|
||||||
|
{paginatedStages.map((stage) => (
|
||||||
|
<div
|
||||||
|
key={stage.id}
|
||||||
|
className="p-2 hover:bg-primary/20 rounded cursor-pointer"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setIsChildClick(true)
|
||||||
|
|
||||||
|
if (extraData?.theory_craft?.stage_id !== Number(stage.id)) {
|
||||||
|
setExtraData({
|
||||||
|
...extraData,
|
||||||
|
theory_craft: {
|
||||||
|
stage_id: Number(stage.id),
|
||||||
|
cycle_count: extraData?.theory_craft?.cycle_count || 1,
|
||||||
|
mode: extraData?.theory_craft?.mode || false,
|
||||||
|
hp: extraData?.theory_craft?.hp || {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setShowSearchStage(pre => !pre)
|
||||||
|
onChangeSearch("")
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{stage.name}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="text-sm text-center py-4">{transI18n("noStageFound")}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{paginatedStages.length > 0 && (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||||
|
<button
|
||||||
|
disabled={stagePage === 1}
|
||||||
|
className="btn btn-sm btn-outline btn-success mt-2"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setStagePage(stagePage - 1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{transI18n("previous")}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
disabled={!hasMorePages}
|
||||||
|
className="btn btn-sm btn-outline btn-success mt-2"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setStagePage(stagePage + 1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{transI18n("next")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</motion.div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
|
||||||
import {
|
import {
|
||||||
Plus,
|
Plus,
|
||||||
Trash2,
|
Trash2,
|
||||||
@@ -88,7 +87,7 @@ export default function CeBar() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMonsterPage(1) // reset về trang 1 khi searchTerm thay đổi
|
setMonsterPage(1)
|
||||||
}, [searchTerm])
|
}, [searchTerm])
|
||||||
|
|
||||||
const stageList = useMemo(() => Object.values(Stage).map((stage) => ({
|
const stageList = useMemo(() => Object.values(Stage).map((stage) => ({
|
||||||
@@ -146,12 +145,11 @@ export default function CeBar() {
|
|||||||
|
|
||||||
<div className="mb-4 w-full relative">
|
<div className="mb-4 w-full relative">
|
||||||
<div className="flex items-center justify-center gap-2">
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-outline w-full text-left flex items-center gap-2"
|
className="btn btn-outline w-full text-left flex items-center gap-2"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setShowSearchStage(true)
|
setShowSearchStage(!showSearchStage)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Search className="w-6 h-6" />
|
<Search className="w-6 h-6" />
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default function SelectCustomImage({ customSet, excludeSet, selectedCusto
|
|||||||
}
|
}
|
||||||
|
|
||||||
const formatOptionLabel = (option: SelectOption) => (
|
const formatOptionLabel = (option: SelectOption) => (
|
||||||
<div className="flex items-center gap-1 w-full h-full z-50">
|
<div className="flex items-center gap-1 w-full h-full">
|
||||||
<Image src={option.imageUrl} alt="" width={125} height={125} className="w-8 h-8 object-contain bg-warning-content rounded-full" />
|
<Image src={option.imageUrl} alt="" width={125} height={125} className="w-8 h-8 object-contain bg-warning-content rounded-full" />
|
||||||
<ParseText className='font-bold' text={option.label} locale={locale} />
|
<ParseText className='font-bold' text={option.label} locale={locale} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default function SelectCustomText({ customSet, excludeSet, selectedCustom
|
|||||||
|
|
||||||
|
|
||||||
const formatOptionLabel = (option: SelectOption) => (
|
const formatOptionLabel = (option: SelectOption) => (
|
||||||
<div className="flex flex-col gap-1 w-full h-full z-50">
|
<div className="flex flex-col gap-1 w-full h-full">
|
||||||
<div
|
<div
|
||||||
className="font-bold text-lg"
|
className="font-bold text-lg"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export interface ExtraData {
|
|||||||
hp: Record<string, number[]>
|
hp: Record<string, number[]>
|
||||||
cycle_count: number
|
cycle_count: number
|
||||||
mode: boolean
|
mode: boolean
|
||||||
|
stage_id: number
|
||||||
}
|
}
|
||||||
setting?: {
|
setting?: {
|
||||||
censorship: boolean
|
censorship: boolean
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ export const extraDataSchema = z.object({
|
|||||||
theory_craft: z.object({
|
theory_craft: z.object({
|
||||||
hp: z.record(z.string(), z.array(z.number())),
|
hp: z.record(z.string(), z.array(z.number())),
|
||||||
cycle_count: z.number(),
|
cycle_count: z.number(),
|
||||||
mode: z.boolean()
|
mode: z.boolean(),
|
||||||
|
stage_id: z.number()
|
||||||
}),
|
}),
|
||||||
setting: z.object({
|
setting: z.object({
|
||||||
censorship: z.boolean(),
|
censorship: z.boolean(),
|
||||||
|
|||||||
Reference in New Issue
Block a user