UPDATE: Responsive for mobile
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m53s
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m53s
This commit is contained in:
@@ -376,8 +376,8 @@ export default function ActionBar() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dialog id="update_profile_modal" className="modal ">
|
<dialog id="update_profile_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
@@ -419,7 +419,7 @@ export default function ActionBar() {
|
|||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<dialog id="copy_profile_modal" className="modal">
|
<dialog id="copy_profile_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
@@ -444,7 +444,7 @@ export default function ActionBar() {
|
|||||||
|
|
||||||
|
|
||||||
<dialog id="avatars_modal" className="modal">
|
<dialog id="avatars_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ export default function AvatarInfo() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<dialog id="action_detail_modal" className="modal backdrop-blur-sm">
|
<dialog id="action_detail_modal" className="modal backdrop-blur-sm">
|
||||||
<div className="modal-box w-11/12 max-w-5xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-5xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ const themes = [
|
|||||||
export default function Header() {
|
export default function Header() {
|
||||||
const { changeTheme } = useChangeTheme()
|
const { changeTheme } = useChangeTheme()
|
||||||
const { locale, setLocale } = useLocaleStore()
|
const { locale, setLocale } = useLocaleStore()
|
||||||
const {
|
const {
|
||||||
avatars,
|
avatars,
|
||||||
battle_type,
|
battle_type,
|
||||||
setAvatars,
|
setAvatars,
|
||||||
setBattleType,
|
setBattleType,
|
||||||
moc_config,
|
moc_config,
|
||||||
pf_config,
|
pf_config,
|
||||||
@@ -49,10 +49,10 @@ export default function Header() {
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const transI18n = useTranslations("DataPage")
|
const transI18n = useTranslations("DataPage")
|
||||||
const {
|
const {
|
||||||
setIsOpenImport,
|
setIsOpenImport,
|
||||||
isOpenImport,
|
isOpenImport,
|
||||||
setIsOpenMonster,
|
setIsOpenMonster,
|
||||||
isOpenMonster,
|
isOpenMonster,
|
||||||
setIsOpenConnect,
|
setIsOpenConnect,
|
||||||
isOpenConnect
|
isOpenConnect
|
||||||
@@ -234,25 +234,25 @@ export default function Header() {
|
|||||||
<details>
|
<details>
|
||||||
<summary className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium">{transI18n("exportData")}</summary>
|
<summary className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium">{transI18n("exportData")}</summary>
|
||||||
<ul className="p-2">
|
<ul className="p-2">
|
||||||
<li><a onClick={() => downloadJson("freesr-data",
|
<li><a onClick={() => downloadJson("freesr-data",
|
||||||
converterToFreeSRJson(
|
converterToFreeSRJson(
|
||||||
avatars,
|
avatars,
|
||||||
battle_type,
|
battle_type,
|
||||||
moc_config,
|
moc_config,
|
||||||
pf_config,
|
pf_config,
|
||||||
as_config,
|
as_config,
|
||||||
ce_config,
|
ce_config,
|
||||||
peak_config
|
peak_config
|
||||||
)
|
)
|
||||||
)}>{transI18n("freeSr")}</a></li>
|
)}>{transI18n("freeSr")}</a></li>
|
||||||
<li><a onClick={() => downloadJson("database-data", {
|
<li><a onClick={() => downloadJson("database-data", {
|
||||||
avatars: avatars,
|
avatars: avatars,
|
||||||
battle_type: battle_type,
|
battle_type: battle_type,
|
||||||
moc_config: moc_config,
|
moc_config: moc_config,
|
||||||
pf_config: pf_config,
|
pf_config: pf_config,
|
||||||
as_config: as_config,
|
as_config: as_config,
|
||||||
ce_config: ce_config,
|
ce_config: ce_config,
|
||||||
peak_config: peak_config
|
peak_config: peak_config
|
||||||
})}>{transI18n("database")}</a></li>
|
})}>{transI18n("database")}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
@@ -341,25 +341,25 @@ export default function Header() {
|
|||||||
<details>
|
<details>
|
||||||
<summary className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium">{transI18n("exportData")}</summary>
|
<summary className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium">{transI18n("exportData")}</summary>
|
||||||
<ul className="p-2">
|
<ul className="p-2">
|
||||||
<li><a onClick={() => downloadJson("freesr-data",
|
<li><a onClick={() => downloadJson("freesr-data",
|
||||||
converterToFreeSRJson(
|
converterToFreeSRJson(
|
||||||
avatars,
|
avatars,
|
||||||
battle_type,
|
battle_type,
|
||||||
moc_config,
|
moc_config,
|
||||||
pf_config,
|
pf_config,
|
||||||
as_config,
|
as_config,
|
||||||
ce_config,
|
ce_config,
|
||||||
peak_config
|
peak_config
|
||||||
)
|
)
|
||||||
)}>{transI18n("freeSr")}</a></li>
|
)}>{transI18n("freeSr")}</a></li>
|
||||||
<li><a onClick={() => downloadJson("database-data", {
|
<li><a onClick={() => downloadJson("database-data", {
|
||||||
avatars: avatars,
|
avatars: avatars,
|
||||||
battle_type: battle_type,
|
battle_type: battle_type,
|
||||||
moc_config: moc_config,
|
moc_config: moc_config,
|
||||||
pf_config: pf_config,
|
pf_config: pf_config,
|
||||||
as_config: as_config,
|
as_config: as_config,
|
||||||
ce_config: ce_config,
|
ce_config: ce_config,
|
||||||
peak_config: peak_config
|
peak_config: peak_config
|
||||||
})}>{transI18n("database")}</a></li>
|
})}>{transI18n("database")}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
@@ -495,8 +495,8 @@ export default function Header() {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dialog id="connect_modal" className="modal sm:modal-middle backdrop-blur-sm">
|
<dialog id="connect_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
@@ -597,71 +597,73 @@ export default function Header() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row justify-between items-center mt-6 mb-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6 mb-2">
|
||||||
<div className="mb-4 sm:mb-0">
|
{/* Status */}
|
||||||
|
<div className="flex items-center justify-center md:justify-start">
|
||||||
<span className="text-md mr-2">{transI18n("status")}:</span>
|
<span className="text-md mr-2">{transI18n("status")}:</span>
|
||||||
<span className={`badge ${isConnectPS ? 'badge-success' : 'badge-error'} badge-lg`}>
|
<span
|
||||||
|
className={`badge ${isConnectPS ? "badge-success" : "badge-error"
|
||||||
|
} badge-lg`}
|
||||||
|
>
|
||||||
{isConnectPS ? transI18n("connected") : transI18n("unconnected")}
|
{isConnectPS ? transI18n("connected") : transI18n("unconnected")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex space-x-2">
|
{/* Buttons */}
|
||||||
|
<div className="flex flex-col sm:flex-row gap-2 w-full justify-center md:justify-end">
|
||||||
<button
|
<button
|
||||||
onClick={
|
onClick={async () => {
|
||||||
async () => {
|
const response = await connectToPS();
|
||||||
const response = await connectToPS()
|
if (response.success) {
|
||||||
if (response.success) {
|
setIsConnectPS(true);
|
||||||
setIsConnectPS(true)
|
setMessage({
|
||||||
setMessage({
|
type: "success",
|
||||||
type: "success",
|
text: transI18n("connectedSuccess"),
|
||||||
text: transI18n("connectedSuccess")
|
});
|
||||||
})
|
} else {
|
||||||
} else {
|
setIsConnectPS(false);
|
||||||
setIsConnectPS(false)
|
setMessage({
|
||||||
setMessage({
|
type: "error",
|
||||||
type: "error",
|
text: response.message,
|
||||||
text: response.message
|
});
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
className={`btn btn-primary`}
|
className="btn btn-primary w-full sm:w-auto"
|
||||||
|
|
||||||
>
|
>
|
||||||
{transI18n("connectPs")}
|
{transI18n("connectPs")}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{isConnectPS && (
|
{isConnectPS && (
|
||||||
<button
|
<button
|
||||||
onClick={
|
onClick={async () => {
|
||||||
async () => {
|
const response = await syncDataToPS();
|
||||||
const response = await syncDataToPS()
|
if (response.success) {
|
||||||
if (response.success) {
|
setMessage({
|
||||||
setMessage({
|
type: "success",
|
||||||
type: "success",
|
text: transI18n("syncSuccess"),
|
||||||
text: transI18n("syncSuccess")
|
});
|
||||||
})
|
} else {
|
||||||
} else {
|
setMessage({
|
||||||
setMessage({
|
type: "error",
|
||||||
type: "error",
|
text: `${transI18n("syncFailed")}: ${response.message}`,
|
||||||
text: `${transI18n("syncFailed")}: ${response.message}`
|
});
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
className={`btn btn-success`}
|
className="btn btn-success w-full sm:w-auto"
|
||||||
>
|
>
|
||||||
{transI18n("sync")}
|
{transI18n("sync")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
|
|
||||||
<dialog id="import_modal" className="modal backdrop-blur-sm">
|
<dialog id="import_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-max bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
@@ -687,8 +689,8 @@ export default function Header() {
|
|||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<dialog id="monster_modal" className="modal sm:backdrop-blur-sm md:backdrop-blur-none">
|
<dialog id="monster_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-max bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
|
|||||||
@@ -20,22 +20,22 @@ export default function RelicMaker() {
|
|||||||
const { avatarSelected } = useAvatarStore()
|
const { avatarSelected } = useAvatarStore()
|
||||||
const { setIsOpenRelic } = useModelStore()
|
const { setIsOpenRelic } = useModelStore()
|
||||||
const { mapRelicInfo } = useRelicStore()
|
const { mapRelicInfo } = useRelicStore()
|
||||||
const { mapMainAffix, mapSubAffix} = useAffixStore()
|
const { mapMainAffix, mapSubAffix } = useAffixStore()
|
||||||
const transI18n = useTranslations("DataPage")
|
const transI18n = useTranslations("DataPage")
|
||||||
const {
|
const {
|
||||||
selectedRelicSlot,
|
selectedRelicSlot,
|
||||||
selectedRelicSet,
|
selectedRelicSet,
|
||||||
selectedMainStat,
|
selectedMainStat,
|
||||||
listSelectedSubStats,
|
listSelectedSubStats,
|
||||||
selectedRelicLevel,
|
selectedRelicLevel,
|
||||||
preSelectedSubStats,
|
preSelectedSubStats,
|
||||||
setSelectedRelicSet,
|
setSelectedRelicSet,
|
||||||
setSelectedMainStat,
|
setSelectedMainStat,
|
||||||
setSelectedRelicLevel,
|
setSelectedRelicLevel,
|
||||||
setListSelectedSubStats,
|
setListSelectedSubStats,
|
||||||
resetHistory,
|
resetHistory,
|
||||||
popHistory,
|
popHistory,
|
||||||
addHistory,
|
addHistory,
|
||||||
} = useRelicMakerStore()
|
} = useRelicMakerStore()
|
||||||
|
|
||||||
const relicSets = useMemo(() => {
|
const relicSets = useMemo(() => {
|
||||||
@@ -59,9 +59,9 @@ export default function RelicMaker() {
|
|||||||
const listSet: Record<string, AffixDetail> = {};
|
const listSet: Record<string, AffixDetail> = {};
|
||||||
const subAffixMap = mapSubAffix["5"];
|
const subAffixMap = mapSubAffix["5"];
|
||||||
const mainAffixMap = mapMainAffix["5" + selectedRelicSlot]
|
const mainAffixMap = mapMainAffix["5" + selectedRelicSlot]
|
||||||
|
|
||||||
if (Object.keys(subAffixMap || {}).length === 0 || Object.keys(mainAffixMap || {}).length === 0) return listSet;
|
if (Object.keys(subAffixMap || {}).length === 0 || Object.keys(mainAffixMap || {}).length === 0) return listSet;
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(subAffixMap)) {
|
for (const [key, value] of Object.entries(subAffixMap)) {
|
||||||
if (value.property !== mainAffixMap[selectedMainStat]?.property) {
|
if (value.property !== mainAffixMap[selectedMainStat]?.property) {
|
||||||
listSet[key] = value;
|
listSet[key] = value;
|
||||||
@@ -73,15 +73,15 @@ export default function RelicMaker() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subAffixMap = mapSubAffix["5"];
|
const subAffixMap = mapSubAffix["5"];
|
||||||
const mainAffixMap = mapMainAffix["5" + selectedRelicSlot];
|
const mainAffixMap = mapMainAffix["5" + selectedRelicSlot];
|
||||||
|
|
||||||
if (!subAffixMap || !mainAffixMap) return;
|
if (!subAffixMap || !mainAffixMap) return;
|
||||||
|
|
||||||
const mainProp = mainAffixMap[selectedMainStat]?.property;
|
const mainProp = mainAffixMap[selectedMainStat]?.property;
|
||||||
if (!mainProp) return;
|
if (!mainProp) return;
|
||||||
|
|
||||||
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
||||||
let updated = false;
|
let updated = false;
|
||||||
|
|
||||||
for (let i = 0; i < newSubAffixes.length; i++) {
|
for (let i = 0; i < newSubAffixes.length; i++) {
|
||||||
if (newSubAffixes[i].property === mainProp) {
|
if (newSubAffixes[i].property === mainProp) {
|
||||||
newSubAffixes[i].affixId = "";
|
newSubAffixes[i].affixId = "";
|
||||||
@@ -91,9 +91,9 @@ export default function RelicMaker() {
|
|||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated) setListSelectedSubStats(newSubAffixes);
|
if (updated) setListSelectedSubStats(newSubAffixes);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [selectedMainStat, mapSubAffix, mapMainAffix, selectedRelicSlot]);
|
}, [selectedMainStat, mapSubAffix, mapMainAffix, selectedRelicSlot]);
|
||||||
|
|
||||||
const exSubAffixOptions = useMemo(() => {
|
const exSubAffixOptions = useMemo(() => {
|
||||||
@@ -119,9 +119,9 @@ export default function RelicMaker() {
|
|||||||
const data = affixSet[selectedMainStat];
|
const data = affixSet[selectedMainStat];
|
||||||
if (!data) return 0;
|
if (!data) return 0;
|
||||||
|
|
||||||
return calcMainAffixBonus(data, selectedRelicLevel);
|
return calcMainAffixBonus(data, selectedRelicLevel);
|
||||||
}, [mapMainAffix, selectedRelicSlot, selectedMainStat, selectedRelicLevel]);
|
}, [mapMainAffix, selectedRelicSlot, selectedMainStat, selectedRelicLevel]);
|
||||||
|
|
||||||
const handleSubStatChange = (key: string, index: number, rollCount: number, stepCount: number) => {
|
const handleSubStatChange = (key: string, index: number, rollCount: number, stepCount: number) => {
|
||||||
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
||||||
if (!subAffixOptions[key]) {
|
if (!subAffixOptions[key]) {
|
||||||
@@ -155,7 +155,7 @@ export default function RelicMaker() {
|
|||||||
newSubAffixes[index].stepCount = preSubAffixes.stepCount;
|
newSubAffixes[index].stepCount = preSubAffixes.stepCount;
|
||||||
setListSelectedSubStats(newSubAffixes);
|
setListSelectedSubStats(newSubAffixes);
|
||||||
popHistory(index);
|
popHistory(index);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetSubStat = (index: number) => {
|
const resetSubStat = (index: number) => {
|
||||||
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
const newSubAffixes = cloneDeep(listSelectedSubStats);
|
||||||
@@ -172,7 +172,7 @@ export default function RelicMaker() {
|
|||||||
const exKeys = Object.keys(exSubAffixOptions);
|
const exKeys = Object.keys(exSubAffixOptions);
|
||||||
for (let i = 0; i < newSubAffixes.length; i++) {
|
for (let i = 0; i < newSubAffixes.length; i++) {
|
||||||
const keys = Object.keys(subAffixOptions).filter((key) => !exKeys.includes(key));
|
const keys = Object.keys(subAffixOptions).filter((key) => !exKeys.includes(key));
|
||||||
const randomKey = keys[Math.floor(Math.random() * keys.length )];
|
const randomKey = keys[Math.floor(Math.random() * keys.length)];
|
||||||
exKeys.push(randomKey);
|
exKeys.push(randomKey);
|
||||||
const randomValue = subAffixOptions[randomKey];
|
const randomValue = subAffixOptions[randomKey];
|
||||||
newSubAffixes[i].affixId = randomKey;
|
newSubAffixes[i].affixId = randomKey;
|
||||||
@@ -326,18 +326,18 @@ export default function RelicMaker() {
|
|||||||
{/* Right Panel - Sub Stats */}
|
{/* Right Panel - Sub Stats */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Total Roll */}
|
{/* Total Roll */}
|
||||||
<div className="bg-base-100 rounded-xl p-6 border border-slate-700 z-[1]">
|
<div className="bg-base-100 rounded-xl p-4 border border-slate-700 z-[1]">
|
||||||
<h3 className="text-lg font-bold mb-4">{transI18n("totalRoll")} {listSelectedSubStats.reduce((a, b) => a + b.rollCount, 0)}</h3>
|
<h3 className="text-lg font-bold mb-4">{transI18n("totalRoll")} {listSelectedSubStats.reduce((a, b) => a + b.rollCount, 0)}</h3>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
<button
|
<button
|
||||||
className="btn btn-outline btn-success"
|
className="btn btn-outline btn-success sm:btn-sm"
|
||||||
onClick={randomizeStats}
|
onClick={randomizeStats}
|
||||||
>
|
>
|
||||||
{transI18n("randomizeStats")}
|
{transI18n("randomizeStats")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-outline btn-success"
|
className="btn btn-outline btn-success sm:btn-sm"
|
||||||
onClick={randomizeRolls}
|
onClick={randomizeRolls}
|
||||||
>
|
>
|
||||||
{transI18n("randomizeRolls")}
|
{transI18n("randomizeRolls")}
|
||||||
@@ -345,118 +345,118 @@ export default function RelicMaker() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{listSelectedSubStats.map((v, index) => (
|
{listSelectedSubStats.map((v, index) => (
|
||||||
<div key={index} className={`bg-base-100 rounded-xl p-4 border border-slate-700`}>
|
<div key={index} className={`bg-base-100 rounded-xl p-4 border border-slate-700`}>
|
||||||
<div className="grid grid-cols-12 gap-2 items-center">
|
<div className="grid grid-cols-12 gap-2 items-center">
|
||||||
|
|
||||||
{/* Stat Selection */}
|
{/* Stat Selection */}
|
||||||
<div className="col-span-8">
|
<div className="col-span-8">
|
||||||
<SelectCustomImage
|
<SelectCustomImage
|
||||||
customSet={Object.entries(subAffixOptions).map(([key, value]) => ({
|
customSet={Object.entries(subAffixOptions).map(([key, value]) => ({
|
||||||
value: key,
|
value: key,
|
||||||
label: mappingStats[value.property].name + " " + mappingStats[value.property].unit,
|
label: mappingStats[value.property].name + " " + mappingStats[value.property].unit,
|
||||||
imageUrl: mappingStats[value.property].icon
|
imageUrl: mappingStats[value.property].icon
|
||||||
}))}
|
}))}
|
||||||
excludeSet={Object.entries(exSubAffixOptions).map(([key, value]) => ({
|
excludeSet={Object.entries(exSubAffixOptions).map(([key, value]) => ({
|
||||||
value: key,
|
value: key,
|
||||||
label: mappingStats[value.property].name + " " + mappingStats[value.property].unit,
|
label: mappingStats[value.property].name + " " + mappingStats[value.property].unit,
|
||||||
imageUrl: mappingStats[value.property].icon
|
imageUrl: mappingStats[value.property].icon
|
||||||
}))}
|
}))}
|
||||||
selectedCustomSet={v.affixId}
|
selectedCustomSet={v.affixId}
|
||||||
placeholder={transI18n("selectASubStat")}
|
placeholder={transI18n("selectASubStat")}
|
||||||
setSelectedCustomSet={(key) => handleSubStatChange(key, index, 0, 0)}
|
setSelectedCustomSet={(key) => handleSubStatChange(key, index, 0, 0)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Current Value */}
|
{/* Current Value */}
|
||||||
<div className="col-span-4 text-center flex items-center justify-center gap-2">
|
<div className="col-span-4 text-center flex items-center justify-center gap-2">
|
||||||
<span className="text-2xl font-mono">+{ }</span>
|
<span className="text-2xl font-mono">+{ }</span>
|
||||||
<div className="text-xl font-bold text-info">{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount, v.rollCount)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}</div>
|
<div className="text-xl font-bold text-info">{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount, v.rollCount)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Up Roll Values */}
|
{/* Up Roll Values */}
|
||||||
<div className="col-span-12">
|
<div className="col-span-12">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<ChevronUp className="w-4 h-4 text-success" />
|
<ChevronUp className="w-4 h-4 text-success" />
|
||||||
<span className="text-sm font-semibold text-success">{transI18n("upRoll")}</span>
|
<span className="text-sm font-semibold text-success">{transI18n("upRoll")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-1">
|
<div className="grid grid-cols-3 gap-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 0)}
|
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 0)}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], 0 , v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], 0, v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 1)}
|
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 1)}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount + 1, v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount + 1, v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 2)}
|
onClick={() => handleSubStatChange(v.affixId, index, v.rollCount + 1, v.stepCount + 2)}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount + 2, v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], v.stepCount + 2, v.rollCount + 1)}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Down Roll Values */}
|
{/* Down Roll Values */}
|
||||||
<div className="col-span-12">
|
<div className="col-span-12">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<ChevronDown className="w-4 h-4 text-error" />
|
<ChevronDown className="w-4 h-4 text-error" />
|
||||||
<span className="text-sm font-semibold text-error">{transI18n("downRoll")}</span>
|
<span className="text-sm font-semibold text-error">{transI18n("downRoll")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-1">
|
<div className="grid grid-cols-3 gap-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount, 0))}
|
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount, 0))}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], 0 , Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], 0, Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount - 1, 0))}
|
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount - 1, 0))}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], Math.max(v.stepCount - 1, 0), Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], Math.max(v.stepCount - 1, 0), Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount - 2, 0))}
|
onClick={() => handleSubStatChange(v.affixId, index, Math.max(v.rollCount - 1, 0), Math.max(v.stepCount - 2, 0))}
|
||||||
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
className="btn btn-sm bg-white text-slate-800 hover:bg-gray-200 border-0"
|
||||||
>
|
>
|
||||||
{calcAffixBonus(subAffixOptions[v.affixId], Math.max(v.stepCount - 2, 0), Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
{calcAffixBonus(subAffixOptions[v.affixId], Math.max(v.stepCount - 2, 0), Math.max(v.rollCount - 1, 0))}{mappingStats?.[subAffixOptions[v.affixId]?.property]?.unit || ""}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Reset Button & Roll Info */}
|
{/* Reset Button & Roll Info */}
|
||||||
<div className="col-span-12 text-center">
|
<div className="col-span-12 text-center w-full">
|
||||||
<div className="grid grid-cols-2 gap-1 items-center justify-items-start">
|
<div className="grid grid-rows-2 gap-1 items-center justify-items-start w-full">
|
||||||
<div className="flex items-center gap-2">
|
<div className="grid grid-cols-2 gap-2 items-center w-full">
|
||||||
<button
|
<button
|
||||||
className="btn btn-error btn-sm mb-1"
|
className="btn btn-error btn-sm mb-1"
|
||||||
onClick={() => resetSubStat(index)}
|
onClick={() => resetSubStat(index)}
|
||||||
>
|
>
|
||||||
{transI18n("reset")}
|
{transI18n("reset")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-warning btn-sm mb-1"
|
className="btn btn-warning btn-sm mb-1"
|
||||||
onClick={() => handlerRollback(index)}
|
onClick={() => handlerRollback(index)}
|
||||||
>
|
>
|
||||||
{transI18n("rollBack")}
|
{transI18n("rollBack")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-lg flex items-center gap-2 text-gray-400">
|
<div className="grid grid-cols-2 gap-2 items-center w-full">
|
||||||
<span className="font-bold">{transI18n("roll")}: <span className="text-info">{v.rollCount}</span></span>
|
<span className="font-bold">{transI18n("roll")}: <span className="text-info">{v.rollCount}</span></span>
|
||||||
<span className="font-bold">{transI18n("step")}: <span className="text-info">{v.stepCount}</span></span>
|
<span className="font-bold">{transI18n("step")}: <span className="text-info">{v.stepCount}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -315,8 +315,8 @@ export default function RelicsInfo() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dialog id="action_detail_modal" className="modal lg:backdrop-blur-sm z-10">
|
<dialog id="action_detail_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
@@ -335,8 +335,8 @@ export default function RelicsInfo() {
|
|||||||
|
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<dialog id="quick_view_modal" className="modal lg:backdrop-blur-sm z-10">
|
<dialog id="quick_view_modal" className="modal">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl max-h-[85vh] bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.1, rotate: 90 }}
|
whileHover={{ scale: 1.1, rotate: 90 }}
|
||||||
|
|||||||
Reference in New Issue
Block a user