mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
create download maps modal
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { MapFilter, MapTag } from "shared/models/maps/beat-saver.model"
|
||||
import {motion} from "framer-motion"
|
||||
import { MutableRefObject} from "react"
|
||||
import { MAP_TYPES } from "renderer/partials/map-tags/map-types"
|
||||
import { MAP_STYLES } from "renderer/partials/map-tags/map-styles"
|
||||
import { MAP_TYPES } from "renderer/partials/maps/map-tags/map-types"
|
||||
import { MAP_STYLES } from "renderer/partials/maps/map-tags/map-styles"
|
||||
import { BsmCheckbox } from "../shared/bsm-checkbox.component"
|
||||
import { diffColors } from "./map-item.component"
|
||||
import { min_to_s } from "renderer/helpers/time-utils"
|
||||
@@ -13,7 +13,7 @@ export type Props = {
|
||||
className?: string,
|
||||
ref?: MutableRefObject<undefined>
|
||||
playlist?: boolean,
|
||||
filter?: MapFilter
|
||||
filter: MapFilter
|
||||
onChange?: (filter: MapFilter) => void
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange}
|
||||
}
|
||||
|
||||
const onNpssChange = ([min, max]: number[]) => {
|
||||
const newFilter: MapFilter = {...(filter ?? {}), minNps: min, maxNps: max};
|
||||
const newFilter: MapFilter = {...filter, minNps: min, maxNps: max};
|
||||
if(max === MAX_NPS){
|
||||
delete newFilter["maxNps"];
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange}
|
||||
}
|
||||
|
||||
const onDurationsChange = ([min, max]: number[]) => {
|
||||
const newFilter: MapFilter = {...(filter ?? {}), minDuration: min, maxDuration: max};
|
||||
const newFilter: MapFilter = {...filter, minDuration: min, maxDuration: max};
|
||||
if(max === MAX_DURATION){
|
||||
delete newFilter["maxDuration"];
|
||||
}
|
||||
@@ -128,40 +128,40 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange}
|
||||
<div className="w-full h-full flex gap-x-2"> {/* TODO TRADUIRE */}
|
||||
<section className="shrink-0">
|
||||
<h2 className="mb-1 uppercase text-sm">general</h2>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("automapper")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("automapper")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.automapper} onChange={() => handleCheckbox("automapper")}/>
|
||||
<span className="grow capitalize">AI</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("ranked")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("ranked")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.ranked} onChange={() => handleCheckbox("ranked")}/>
|
||||
<span className="grow capitalize">Rancked</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("curated")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("curated")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.curated} onChange={() => handleCheckbox("curated")}/>
|
||||
<span className="grow capitalize">Curated</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("verified")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("verified")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.verified} onChange={() => handleCheckbox("verified")}/>
|
||||
<span className="grow capitalize">Verified Mapper</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("fullSpread")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("fullSpread")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.fullSpread} onChange={() => handleCheckbox("fullSpread")}/>
|
||||
<span className="grow capitalize">Full Spread</span>
|
||||
</div>
|
||||
<h2 className="my-1 uppercase text-sm">requirements</h2>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("chroma")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("chroma")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.chroma} onChange={() => handleCheckbox("chroma")}/>
|
||||
<span className="grow capitalize">Chroma</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("noodle")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("noodle")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.noodle} onChange={() => handleCheckbox("noodle")}/>
|
||||
<span className="grow capitalize">Noodle</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("me")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("me")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.me} onChange={() => handleCheckbox("me")}/>
|
||||
<span className="grow capitalize" title="Mapping Extensions">Me</span>
|
||||
</div>
|
||||
<div className="flex justify-start items-center h-6 z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("cinema")}>
|
||||
<div className="flex justify-start items-center h-[22px] z-20 relative py-0.5 cursor-pointer" onClick={e => handleCheckbox("cinema")}>
|
||||
<BsmCheckbox className="h-full aspect-square relative bg-inherit mr-1" checked={filter?.cinema} onChange={() => handleCheckbox("cinema")}/>
|
||||
<span className="grow capitalize">Cinema</span>
|
||||
</div>
|
||||
|
||||
+4
-2
@@ -10,6 +10,7 @@ import { useThemeColor } from "renderer/hooks/use-theme-color.hook"
|
||||
import { MapsManagerService } from "renderer/services/maps-manager.service"
|
||||
import { motion, Variants } from "framer-motion";
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { MapsDownloaderService } from "renderer/services/maps-downloader.service"
|
||||
|
||||
type Props = {
|
||||
oneBlock?: boolean,
|
||||
@@ -19,6 +20,7 @@ type Props = {
|
||||
export function MapsPlaylistsPanel({version, oneBlock = false}: Props) {
|
||||
|
||||
const mapsService = MapsManagerService.getInstance();
|
||||
const mapsDownloader = MapsDownloaderService.getInstance();
|
||||
|
||||
const [tabIndex, setTabIndex] = useState(0);
|
||||
const [mapFilter, setMapFilter] = useState<MapFilter>({
|
||||
@@ -58,7 +60,7 @@ export function MapsPlaylistsPanel({version, oneBlock = false}: Props) {
|
||||
}
|
||||
|
||||
const handleMapsAddClick = () => {
|
||||
|
||||
mapsDownloader.openDownloadMapModal(version);
|
||||
}
|
||||
|
||||
const handlePlaylistAddClick = () => {
|
||||
@@ -90,7 +92,7 @@ export function MapsPlaylistsPanel({version, oneBlock = false}: Props) {
|
||||
</motion.div>
|
||||
<motion.div variants={variants} whileHover="hover" whileTap="tap" initial={{rotate: 0}} className="absolute block p-1 right-11 h-[calc(100%-5px)] aspect-square blur-0 hover:brightness-75" data-tip data-for="add-tooltip">
|
||||
<span className="absolute top-0 left-0 h-full w-full rounded-full opacity-20" style={{backgroundColor: mainColor}}/>
|
||||
<BsmButton className="p-0.5 absolute top-0 left-0 h-full w-full !bg-transparent" iconClassName="" icon="add" withBar={false} style={{color: mainColor}} onClick={e => {e.stopPropagation(); onClickLink(index)}}/>
|
||||
<BsmButton className="p-0.5 absolute top-0 left-0 h-full w-full !bg-transparent" iconClassName="" icon="add" withBar={false} style={{color: mainColor}} onClick={e => {e.stopPropagation(); onClickAdd(index)}}/>
|
||||
</motion.div>
|
||||
<ReactTooltip id="add-tooltip" effect="solid" padding="5px" >
|
||||
<span className="whitespace-nowrap">Ajouté des maps</span> {/* TODO TRANSLATE */}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { FilterPanel } from "renderer/components/maps-mangement-components/filter-panel.component";
|
||||
import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { BsmDropdownButton } from "renderer/components/shared/bsm-dropdown-button.component";
|
||||
import { BsmSelect, BsmSelectOption } from "renderer/components/shared/bsm-select.component";
|
||||
import { BSV_SORT_ORDER } from "renderer/partials/beat-saver/sort-order";
|
||||
import { BeatSaverService } from "renderer/services/beat-saver/beat-saver.service";
|
||||
import { ModalComponent } from "renderer/services/modale.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { BsvMapDetail, MapFilter } from "shared/models/maps/beat-saver.model";
|
||||
|
||||
export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
|
||||
|
||||
const beatSaver = BeatSaverService.getInstance();
|
||||
|
||||
const [filter, setFilter] = useState<MapFilter>(null);
|
||||
const [maps, setMaps] = useState<BsvMapDetail[]>(null);
|
||||
const [page, setPage] = useState(0);
|
||||
const [sortOrder, setSortOrder] = useState(BSV_SORT_ORDER.at(0));
|
||||
|
||||
const sortOptions: BsmSelectOption[] = (() => {
|
||||
return BSV_SORT_ORDER.map(sort => ({text: sort, value: sort}));
|
||||
})();
|
||||
|
||||
console.log(maps);
|
||||
|
||||
useEffect(() => {
|
||||
beatSaver.searchMaps({
|
||||
page, sortOrder
|
||||
}).then(setMaps);
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<form className="text-gray-800 dark:text-gray-200 flex flex-col">
|
||||
<div className="flex h-7 gap-2">
|
||||
<BsmDropdownButton className="shrink-0 h-full relative z-[1] flex justify-center" buttonClassName="flex items-center justify-center h-full rounded-full px-2 py-1 !bg-main-color-1" icon="search" text="Filtres" withBar={false}>
|
||||
<FilterPanel className="absolute top-[calc(100%+3px)] bg-main-color-3 origin-top w-[500px] h-fit p-2 rounded-md shadow-md shadow-black" filter={filter} onChange={setFilter}/>
|
||||
</BsmDropdownButton>
|
||||
<input className="h-full bg-main-color-1 rounded-full px-2 grow pb-0.5" type="text" name="" id="" placeholder="Rechercher"/>
|
||||
<BsmButton className="shrink-0 aspect-square rounded-full p-1 !bg-main-color-1" icon="search" withBar={false}/>
|
||||
<BsmSelect className="bg-main-color-1 rounded-full px-2 pb-0.5" options={sortOptions} onChange={setSortOrder}/>
|
||||
</div>
|
||||
<ul>
|
||||
|
||||
</ul>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@@ -20,8 +20,10 @@ export function Modal() {
|
||||
<div className="top-0 absolute w-screen h-screen flex content-center items-center justify-center z-50">
|
||||
<motion.span key="modal-overlay" onClick={() => modalSevice.resolve({exitCode: ModalExitCode.NO_CHOICE})} className="absolute top-0 bottom-0 right-0 left-0 bg-black" initial={{opacity: 0}} animate={{opacity: ModalComponent && .60}} exit={{opacity: 0}} transition={{duration: .2}}/>
|
||||
<motion.div key="modal" initial={{y: "100vh"}} animate={{y: 0}} exit={{y: "100vh"}}>
|
||||
<div className="relative p-4 text-gray-800 dark:text-gray-200 overflow-hidden rounded-md shadow-lg shadow-black bg-gradient-to-br from-light-main-color-3 to-light-main-color-2 dark:from-main-color-3 dark:to-main-color-2">
|
||||
<span className="absolute top-0 w-full left-0 h-1" style={{backgroundImage: `linear-gradient(to right, ${firstColor}, ${secondColor})`}}/>
|
||||
<div className="relative p-4 text-gray-800 dark:text-gray-200 rounded-md shadow-lg shadow-black bg-gradient-to-br from-light-main-color-3 to-light-main-color-2 dark:from-main-color-3 dark:to-main-color-2">
|
||||
<div className="absolute top-0 w-full left-0 h-1 rounded-t-md overflow-hidden">
|
||||
<span className="block w-full h-full" style={{backgroundImage: `linear-gradient(to right, ${firstColor}, ${secondColor})`}}/>
|
||||
</div>
|
||||
<ModalComponent resolver={resolver} data={modalData}/>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ChangeEvent, CSSProperties } from "react"
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
style?: CSSProperties,
|
||||
options?: BsmSelectOption[],
|
||||
onChange?: (value: any) => void
|
||||
}
|
||||
|
||||
export function BsmSelect({className, style, options, onChange}: Props) {
|
||||
|
||||
const handleChange = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||
onChange?.(event.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<select className={className} style={style} onChange={handleChange}>
|
||||
{options && options.map(option => (
|
||||
<option key={option.value} value={option.value}>{option.text}</option>
|
||||
))}
|
||||
</select>
|
||||
)
|
||||
}
|
||||
|
||||
export interface BsmSelectOption{
|
||||
text: string,
|
||||
value: string
|
||||
}
|
||||
Reference in New Issue
Block a user