Compare commits

..
8 Commits
127 changed files with 8567 additions and 4538 deletions

No files matched your search

+19 -10
View File
@@ -1,10 +1,11 @@
plugins { plugins {
id("org.springframework.boot") version "3.3.0" id("org.springframework.boot") version "3.5.12"
id("io.spring.dependency-management") version "1.1.5" id("io.spring.dependency-management") version "1.1.7"
kotlin("plugin.jpa") version "1.9.24" kotlin("plugin.jpa") version "2.3.20"
kotlin("jvm") version "1.9.24" kotlin("jvm") version "2.3.20"
kotlin("plugin.spring") version "1.9.24" kotlin("plugin.spring") version "2.3.20"
kotlin("plugin.allopen") version "1.9.22" kotlin("plugin.allopen") version "2.3.20"
kotlin("kapt") version "2.3.20"
} }
group = "at.eisibaer" group = "at.eisibaer"
@@ -26,23 +27,25 @@ repositories {
mavenCentral() mavenCentral()
} }
val bcVersion: String = "1.78.1"; val bcVersion: String = "1.78.1"
val mapstructVersion: String = "1.7.0.Beta1"
dependencies { dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("org.springframework.boot:spring-boot-starter-websocket")
implementation("org.springframework.boot:spring-boot-docker-compose") implementation("org.springframework.session:spring-session-jdbc")
implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation("org.springframework.session:spring-session-data-redis")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.bouncycastle:bcprov-jdk18on:$bcVersion") implementation("org.bouncycastle:bcprov-jdk18on:$bcVersion")
implementation("org.mapstruct:mapstruct:$mapstructVersion")
implementation("org.jetbrains.kotlin:kotlin-metadata-jvm:2.3.20")
compileOnly("org.projectlombok:lombok") compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools") developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("org.postgresql:postgresql") runtimeOnly("org.postgresql:postgresql")
annotationProcessor("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok")
kapt("org.mapstruct:mapstruct-processor:$mapstructVersion")
testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testImplementation("org.springframework.security:spring-security-test") testImplementation("org.springframework.security:spring-security-test")
@@ -55,6 +58,12 @@ kotlin {
} }
} }
kapt {
arguments {
arg("mapstruct.defaultComponentModel", "spring")
}
}
tasks.withType<Test> { tasks.withType<Test> {
useJUnitPlatform() useJUnitPlatform()
} }
-7
View File
@@ -1,7 +0,0 @@
version: "3.1"
services:
redis:
image: "redis:alpine"
ports:
- "6379:6379"
@@ -7,4 +7,18 @@ data class ApplicationProperties(
val test: Boolean, val test: Boolean,
val corsAllowedOrigins: List<String>, val corsAllowedOrigins: List<String>,
val corsAllowedMethods: List<String>, val corsAllowedMethods: List<String>,
)
val storage: StorageProperties,
){
data class StorageProperties (
val fs: FileSystemStorageProperties,
) {
data class FileSystemStorageProperties(
val location: String,
)
}
}
@@ -47,5 +47,9 @@ class SpringConfiguration(
.addMapping("/api/**") .addMapping("/api/**")
.allowedOrigins(*applicationProperties.corsAllowedOrigins.map { it }.toTypedArray()) .allowedOrigins(*applicationProperties.corsAllowedOrigins.map { it }.toTypedArray())
.allowedMethods(*applicationProperties.corsAllowedMethods.map { it }.toTypedArray()) .allowedMethods(*applicationProperties.corsAllowedMethods.map { it }.toTypedArray())
// registry
// .addMapping("/gs-guide-websocket")
// .allowedOrigins(*applicationProperties.corsAllowedOrigins.map { it }.toTypedArray())
// .allowedMethods(*applicationProperties.corsAllowedMethods.map { it }.toTypedArray())
} }
} }
@@ -2,20 +2,28 @@ package at.eisibaer.jbear2.config
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.messaging.simp.config.MessageBrokerRegistry import org.springframework.messaging.simp.config.MessageBrokerRegistry
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.session.Session
import org.springframework.session.web.socket.config.annotation.AbstractSessionWebSocketMessageBrokerConfigurer
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
import org.springframework.web.socket.config.annotation.StompEndpointRegistry import org.springframework.web.socket.config.annotation.StompEndpointRegistry
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
@Configuration @Configuration
@EnableScheduling
@EnableWebSocketMessageBroker @EnableWebSocketMessageBroker
class WebSocketConfig : WebSocketMessageBrokerConfigurer { class WebSocketConfig(
val applicationProperties: ApplicationProperties,
) : AbstractSessionWebSocketMessageBrokerConfigurer<Session>() {
override fun configureMessageBroker(registry: MessageBrokerRegistry) { override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.enableSimpleBroker("/game");
registry.setApplicationDestinationPrefixes("/app"); registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
} }
override fun registerStompEndpoints(registry: StompEndpointRegistry) { override fun configureStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/websocket") registry
.addEndpoint("/ws")
.setAllowedOrigins(applicationProperties.corsAllowedOrigins.joinToString(","))
} }
} }
@@ -0,0 +1,10 @@
package at.eisibaer.jbear2.dto.board
import org.springframework.data.geo.Point
data class AnswerDto(
val text: String,
val answerType: Int,
val image: String?,
val location: Point?,
)
@@ -0,0 +1,9 @@
package at.eisibaer.jbear2.dto.board
data class BoardDto(
val id: Long?,
val boardName: String,
val owner: String?,
val categories: List<CategoryDto>,
val pointsAreTitle: Boolean,
)
@@ -0,0 +1,9 @@
package at.eisibaer.jbear2.dto.board
data class BoardEntryDto(
val name: String,
val points: Long,
val answer: AnswerDto,
val questions: List<QuestionDto>,
// val category: CategoryDto,
)
@@ -0,0 +1,7 @@
package at.eisibaer.jbear2.dto.board
data class CategoryDto(
val name: String,
val description: String,
val boardEntries: List<BoardEntryDto>,
)
@@ -0,0 +1,12 @@
package at.eisibaer.jbear2.dto.board
import org.springframework.data.geo.Point
data class QuestionDto(
val text: String,
val questionType: Int,
val fontScaling: Int,
val image: String?,
val location: Point?,
// val boardEntryDto: BoardEntryDto,
)
@@ -0,0 +1,14 @@
package at.eisibaer.jbear2.dto.game
import java.util.*
data class GameDto(
val inviteCode: String,
val uuid: UUID,
val boardId: Long,
// val host: String,
val players: List<PlayerDto>,
// val alreadyAnsweredEntries: List<Long>,
val acceptingAnswers: Boolean = false,
val currentlyChoosingPlayer: PlayerDto? = null,
)
@@ -0,0 +1,9 @@
package at.eisibaer.jbear2.dto.game
import java.util.UUID
data class PlayerDto(
val name: String,
val id: Long,
// val uuid: UUID,
)
@@ -0,0 +1,5 @@
package at.eisibaer.jbear2.dto.message
import java.util.*
data class GameMessage(val uuid: UUID, val message: String);
@@ -0,0 +1,12 @@
package at.eisibaer.jbear2.dto.message
import at.eisibaer.jbear2.model.BoardEntry
import java.util.UUID
data class GameStateMessage(
val uuid: UUID,
val categoryIndex: Int?,
val boardEntryIndex: Int?,
val questionIndex: Int?,
val questionLayerIndex: Int?,
)
@@ -4,8 +4,5 @@ import lombok.AllArgsConstructor
@AllArgsConstructor @AllArgsConstructor
data class GenericMessage ( data class GenericMessage (
val content: String,
var name: String? = "",
var content: String? = "",
) )
@@ -0,0 +1,5 @@
package at.eisibaer.jbear2.dto.message
data class JoinGameMessage(
val playerName: String,
)
@@ -0,0 +1,8 @@
package at.eisibaer.jbear2.dto.message
import at.eisibaer.jbear2.dto.game.PlayerDto
data class PlayerMessage(
val player: PlayerDto,
val content: String,
)
@@ -0,0 +1,9 @@
package at.eisibaer.jbear2.dto.user
import at.eisibaer.jbear2.dto.board.BoardDto
data class UserDto(
val username: String,
val profilePicture: String,
val boards: List<BoardDto>,
)
@@ -11,10 +11,7 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
@@ -31,24 +28,24 @@ class AuthEndpoint(
val encoder: PasswordEncoder, val encoder: PasswordEncoder,
) { ) {
private val log: Logger = LoggerFactory.getLogger(AuthEndpoint::class.java); private val log: Logger = LoggerFactory.getLogger(AuthEndpoint::class.java)
val strResponseSuccess: String = "Sending back success response"; val strResponseSuccess: String = "Sending back success response"
val strAlreadyLoggedIn: String = "User already logged in"; val strAlreadyLoggedIn: String = "User already logged in"
@PostMapping("/signup") @PostMapping("/signup")
fun signupUser(@RequestBody loginDto: LoginDto, session: HttpSession): ResponseEntity<*>{ fun signupUser(@RequestBody loginDto: LoginDto, session: HttpSession): ResponseEntity<*>{
log.info("Endpoint signupUser called"); log.info("Endpoint signupUser called")
log.debug("signup Request with username: {}", loginDto.username); log.debug("signup Request with username: {}", loginDto.username)
if( userRepository.existsByUsername(loginDto.username)){ if( userRepository.existsByUsername(loginDto.username)){
log.info("Username was already taken"); log.info("Username was already taken")
return ResponseEntity.badRequest().body("Username already taken"); return ResponseEntity.badRequest().body("Username already taken")
} }
val user = User(loginDto.username, encoder.encode( loginDto.password), ArrayList(), null, null ); val user = User(loginDto.username, encoder.encode( loginDto.password), ArrayList(), null, null )
userRepository.save(user); userRepository.save(user)
val authentication = authenticationManager.authenticate( val authentication = authenticationManager.authenticate(
UsernamePasswordAuthenticationToken( UsernamePasswordAuthenticationToken(
@@ -57,81 +54,69 @@ class AuthEndpoint(
) )
) )
SecurityContextHolder.getContext().authentication = authentication; SecurityContextHolder.getContext().authentication = authentication
val userDetails: UserDetailsImpl = authentication.principal as UserDetailsImpl; val userDetails: UserDetailsImpl = authentication.principal as UserDetailsImpl
session.setAttribute(STR_SESSION_USER_KEY, userDetails); session.setAttribute(STR_SESSION_USER_KEY, userDetails)
log.info(strResponseSuccess); log.info(strResponseSuccess)
return ResponseEntity.ok().body(LoginResponseDto(userDetails.username, userDetails.getProfilePictureFilename())); return ResponseEntity.ok().body(LoginResponseDto(userDetails.username, userDetails.getProfilePictureFilename()))
} }
@PostMapping("/login") @PostMapping("/login")
fun loginUser(@RequestBody loginDto: LoginDto, session: HttpSession): ResponseEntity<*>{ fun loginUser(@RequestBody loginDto: LoginDto, session: HttpSession): ResponseEntity<*>{
log.info("Endpoint loginUser called"); log.info("Endpoint loginUser called")
log.debug("login Request with username: {}", loginDto.username); log.debug("login Request with username: {}", loginDto.username)
if( session.getAttribute(STR_SESSION_USER_KEY) != null ){ if( session.getAttribute(STR_SESSION_USER_KEY) != null ){
log.info(strAlreadyLoggedIn); log.info(strAlreadyLoggedIn)
return ResponseEntity.badRequest().body(strAlreadyLoggedIn); return ResponseEntity.badRequest().body(strAlreadyLoggedIn)
} }
val authentication: Authentication; val authentication = authenticationManager.authenticate(
try{
authentication = authenticationManager.authenticate(
UsernamePasswordAuthenticationToken( UsernamePasswordAuthenticationToken(
loginDto.username, loginDto.username,
loginDto.password loginDto.password
) )
) )
} catch (authenticationException: AuthenticationException ){
if( authenticationException is BadCredentialsException ){
log.debug("Login attempt with bad credentials for username: {}", loginDto.username);
return ResponseEntity.status(401).body(4011);
}
log.error("Error during authentication", authenticationException);
return ResponseEntity.status(401).body(4010);
}
SecurityContextHolder.getContext().authentication = authentication; val userDetails: UserDetailsImpl = authentication.principal as UserDetailsImpl
val userDetails: UserDetailsImpl = authentication.principal as UserDetailsImpl; session.setAttribute(STR_SESSION_USER_KEY, userDetails)
session.setAttribute(STR_SESSION_USER_KEY, userDetails); log.info(strResponseSuccess)
log.info(strResponseSuccess);
return ResponseEntity.ok() return ResponseEntity.ok()
.body( LoginResponseDto(userDetails.username, userDetails.getProfilePictureFilename())) .body( LoginResponseDto(userDetails.username, userDetails.getProfilePictureFilename()))
} }
@PostMapping("/logout") @PostMapping("/logout")
fun logoutUser(session: HttpSession): ResponseEntity<String>{ fun logoutUser(session: HttpSession): ResponseEntity<String>{
log.info("Endpoint logoutUser called"); log.info("Endpoint logoutUser called")
session.invalidate(); session.invalidate()
log.info(strResponseSuccess); log.info(strResponseSuccess)
return ResponseEntity.ok() return ResponseEntity.ok()
.body("Logged out"); .body("Logged out")
} }
@GetMapping("/status") @GetMapping("/status")
fun checkStatus(session: HttpSession): ResponseEntity<*>{ fun checkStatus(session: HttpSession): ResponseEntity<*>{
log.info("Endpoint checkStatus called"); log.info("Endpoint checkStatus called")
return if( session.getAttribute(STR_SESSION_USER_KEY) != null ){ return if( session.getAttribute(STR_SESSION_USER_KEY) != null ){
log.info(strAlreadyLoggedIn); log.info(strAlreadyLoggedIn)
val sessionUser: UserDetailsImpl = session.getAttribute(STR_SESSION_USER_KEY) as UserDetailsImpl; val sessionUser: UserDetailsImpl = session.getAttribute(STR_SESSION_USER_KEY) as UserDetailsImpl
ResponseEntity ResponseEntity
.ok() .ok()
.body( LoginResponseDto( sessionUser.username, sessionUser.getProfilePictureFilename() ) ); .body( LoginResponseDto( sessionUser.username, sessionUser.getProfilePictureFilename() ) )
} else { } else {
log.debug("No user logged in"); log.debug("No user logged in")
log.info(strResponseSuccess); log.info(strResponseSuccess)
ResponseEntity ResponseEntity
.status(401) .status(401)
.body("No user logged in"); .body("No user logged in")
} }
} }
} }
@@ -1,9 +0,0 @@
package at.eisibaer.jbear2.endpoint
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
@Controller
@RequestMapping("/api/board")
class BoardEndpoint {
}
@@ -1,19 +0,0 @@
package at.eisibaer.jbear2.endpoint
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.SendTo
import at.eisibaer.jbear2.dto.message.GenericMessage
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/api/game")
class GameEndpoint {
@MessageMapping("/player/join")
@SendTo("/player/joined")
fun playerJoining(playerJoiningMessage: GenericMessage): GenericMessage{
return playerJoiningMessage.copy(playerJoiningMessage.name, "Joined");
}
}
@@ -1,28 +1,86 @@
package at.eisibaer.jbear2.endpoint package at.eisibaer.jbear2.endpoint
import at.eisibaer.jbear2.dto.board.BoardDto
import at.eisibaer.jbear2.model.User
import at.eisibaer.jbear2.repository.FileRepository
import at.eisibaer.jbear2.repository.UserRepository
import at.eisibaer.jbear2.security.UserDetailsImpl
import at.eisibaer.jbear2.service.BoardService
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.bind.annotation.PathVariable import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.multipart.MultipartFile
import org.springframework.web.bind.annotation.RestController
@RestController @RestController
@RequestMapping("/api/user") @RequestMapping("/api/user")
class UserEndpoint { class UserEndpoint(
val boardService: BoardService,
val userRepository: UserRepository,
val fileRepository: FileRepository,
) {
val log: Logger = LoggerFactory.getLogger(UserEndpoint::class.java); val log: Logger = LoggerFactory.getLogger(UserEndpoint::class.java)
@GetMapping("/test/{pathVar}") @GetMapping("/test/{pathVar}")
fun testEndpoint(@PathVariable pathVar: String, @RequestParam param1: String): ResponseEntity<String>{ fun testEndpoint(@PathVariable pathVar: String, @RequestParam param1: String): ResponseEntity<String>{
log.info("test Endpoint!"); log.info("test Endpoint!")
return ResponseEntity.ok(param1); return ResponseEntity.ok(param1)
} }
@GetMapping("/boards") @GetMapping("/boards")
fun getBoards(){ fun getBoards(): ResponseEntity<List<BoardDto>?>{
TODO(); log.info("Get all Board Endpoint")
val userDetails = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
return boardService.getBoardsByUser( user )
}
@GetMapping("/boards/{boardId}")
fun getBoardById(@PathVariable boardId: Long): ResponseEntity<BoardDto?>{
log.info("Get Board Endpoint with id {}", boardId)
val userDetails: UserDetailsImpl = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
return boardService.getBoardByUserAndId( user, boardId)
}
@PostMapping("/boards")
fun saveNewBoard(@RequestPart("files") files: List<MultipartFile>, @RequestPart("board") boardDto: BoardDto): ResponseEntity<*> {
log.info("Post Board Endpoint")
val userDetails: UserDetailsImpl = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
if( boardDto.id != null ){
return ResponseEntity.badRequest().body(Unit)
}
return boardService.saveBoardToUser( user, boardDto, files )
}
@PutMapping("/boards/{boardId}")
fun saveExistingBoard(@RequestPart("files") files: List<MultipartFile>, @RequestPart("board") boardDto: BoardDto, @PathVariable boardId: Long): ResponseEntity<*> {
log.info("Put Board Endpoint with id {}", boardId)
val userDetails: UserDetailsImpl = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
if( boardDto.id == null || boardDto.id != boardId ){
return ResponseEntity.badRequest().body("ID is either null or does not match")
}
return boardService.saveBoardToUser( user, boardDto, files )
}
@DeleteMapping("/boards/{boardId}")
fun saveNewBoard(@PathVariable boardId: Long): ResponseEntity<*> {
log.info("Delete Board Endpoint with id {}", boardId)
val userDetails: UserDetailsImpl = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
return boardService.deleteBoardOfUser( user, boardId )
} }
} }
@@ -0,0 +1,221 @@
package at.eisibaer.jbear2.endpoint.ws
import at.eisibaer.jbear2.dto.message.*
import at.eisibaer.jbear2.model.Game
import at.eisibaer.jbear2.model.Player
import at.eisibaer.jbear2.model.User
import at.eisibaer.jbear2.repository.BoardRepository
import at.eisibaer.jbear2.repository.GameRepository
import at.eisibaer.jbear2.repository.PlayerRepository
import at.eisibaer.jbear2.repository.UserRepository
import at.eisibaer.jbear2.security.UserDetailsImpl
import at.eisibaer.jbear2.service.mapper.GameMapper
import at.eisibaer.jbear2.service.mapper.PlayerMapper
import at.eisibaer.jbear2.service.mapper.QuestionMapper
import at.eisibaer.jbear2.util.Constants.INVITE_CODE_LENGTH
import at.eisibaer.jbear2.util.RandomString
import jakarta.transaction.Transactional
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.http.ResponseEntity
import org.springframework.messaging.handler.annotation.DestinationVariable
import org.springframework.messaging.handler.annotation.MessageExceptionHandler
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.Payload
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.messaging.simp.annotation.SendToUser
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import java.lang.Exception
import java.util.*
import kotlin.NoSuchElementException
@Controller
class GameEndpoint(
val playerRepository: PlayerRepository,
val userRepository: UserRepository,
val boardRepository: BoardRepository,
val gameRepository: GameRepository,
val playerMapper: PlayerMapper,
val gameMapper: GameMapper,
val questionMapper: QuestionMapper,
val messagingTemplate: SimpMessagingTemplate,
) {
private val log: Logger = LoggerFactory.getLogger(GameEndpoint::class.java)
@Transactional
@GetMapping("/api/games/{id}")
fun getGameByInviteCode(@PathVariable id: String): ResponseEntity<*>{
val game: Game
if( id.length == INVITE_CODE_LENGTH){
game = gameRepository.findByInviteCode(id) ?: return ResponseEntity.status(404).body("Game with invide code $id not found")
} else {
var uuid: UUID
try{
uuid = UUID.fromString(id)
}catch (exception: IllegalArgumentException){
return ResponseEntity.status(400).body("Invalid UUID given")
}
game = gameRepository.findByUuid(uuid) ?: return ResponseEntity.status(404).body("Game with UUID $uuid not found")
}
return ResponseEntity.ok().body(gameMapper.toDto(game))
}
@Transactional
@PostMapping("/api/games")
fun hostNewGame(@RequestBody body: String?): ResponseEntity<*>{
log.info("Start new game")
val userDetails = SecurityContextHolder.getContext().authentication.principal as UserDetailsImpl
val user: User = userRepository.findUserByUsername(userDetails.username) ?: throw UsernameNotFoundException("Username ${userDetails.username} not found in DB")
val firstAvailableBoard = boardRepository.findFirstByOwnerOrderByBoardName(user) ?: return ResponseEntity.status(404).body("No board found for user")
gameRepository.deleteAll()
gameRepository.flush()
val game = Game(RandomString.ofLength(8), UUID.randomUUID(), firstAvailableBoard, user, emptyList(), emptyList(), null )
val savedGame = gameRepository.save(game)
return ResponseEntity.ok().body(gameMapper.toDto(savedGame))
}
// @MessageMapping("/join")
// fun test(joinMessage: GenericMessage, principal: Principal){
// if( joinMessage.content == null ){
// messagingTemplate.convertAndSendToUser(principal.name, "/game/joined", GenericMessage("error", "Received empty message"));
// return
// }
// val game = gameRepository.findByInviteCode(joinMessage.content)
// if( game == null) {
// messagingTemplate.convertAndSendToUser(principal.name, "/game/joined", GenericMessage("error", "No game found"));
// return
// }
// val player = Player("test", game);
// val payload = GenericMessage(player.name, "${player.name} joined");
// messagingTemplate.convertAndSendToUser("TODO ALL", "/game/joined", payload);
// }
// @MessageMapping("/host")
// fun startGame(message: GenericMessage, principal: Principal ){
// log.info("starting to ", principal.name);
// val user = userRepository.findUserByUsername(principal.name) ?: throw UsernameNotFoundException("User not found");
// val board = boardRepository.findFirstByOwnerOrderByBoardName(user)
// if( board == null ){
// messagingTemplate.convertAndSendToUser(principal.name, "/game/created", GenericMessage("error", "No Board available for playing!"));
// return
// }
// val newGame = Game(RandomString.ofLength(8), UUID.randomUUID(), board, user, ArrayList(), ArrayList(), null )
// var savedGame: Game;
// try{
// savedGame = gameRepository.save(newGame);
// } catch (dataIntegrityViolationException: DataIntegrityViolationException){
// log.error("Could not create game", dataIntegrityViolationException)
// messagingTemplate.convertAndSendToUser(principal.name, "/game/created", GenericMessage("error", "Game could not be created!"));
// return
// }
//
// val payload = GenericMessage("created", savedGame.inviteCode);
// messagingTemplate.convertAndSendToUser(principal.name, "/game/created", payload);
// }
@MessageMapping("/join/{id}")
fun playerJoining(@Payload joinMessage: GenericMessage, @DestinationVariable id: String){
val game: Game
if( id.length == INVITE_CODE_LENGTH){
game = gameRepository.findByInviteCode(id) ?: throw NoSuchElementException("Game with invide code $id not found")
} else {
var uuid: UUID
try{
uuid = UUID.fromString(id)
}catch (exception: IllegalArgumentException){
throw IllegalArgumentException("Invalid UUID given")
}
game = gameRepository.findByUuid(uuid) ?: throw NoSuchElementException("Game with UUID $uuid not found")
}
val player = Player(joinMessage.content, game)
val savedPlayer = playerRepository.save(player)
val payload = playerMapper.toDto(savedPlayer)
messagingTemplate.convertAndSend("/topic/game/${game.uuid}/joined", payload)
}
@MessageMapping("/host/game/{uuid}/start")
fun startGame(@Payload startMessage: GenericMessage, @DestinationVariable uuid: UUID){
// val game = gameRepository.findByUuid(uuid) ?: throw NoSuchElementException("Game with UUID $uuid not found")
messagingTemplate.convertAndSend("/topic/game/$uuid/started", GameMessage(uuid, "The game has been started"))
}
@MessageMapping("/host/game/{uuid}/board/select")
fun selectBoard(@Payload boardMessage: GenericMessage, @DestinationVariable uuid: UUID){
messagingTemplate.convertAndSend("/topic/game/$uuid/board/selected", GameMessage(uuid, "The board is being shown"))
}
@MessageMapping("/host/game/{uuid}/boardentry/select")
fun selectBoardEntry(@Payload targetGameState: GameStateMessage, @DestinationVariable uuid: UUID){
val gameState = GameStateMessage(
uuid,
targetGameState.categoryIndex,
targetGameState.boardEntryIndex,
null,
null,
)
messagingTemplate.convertAndSend("/topic/game/$uuid/boardentry/selected", gameState)
}
@MessageMapping("/host/game/{uuid}/question/layer/select")
fun selectQuestionLayer(@Payload targetGameState: GameStateMessage, @DestinationVariable uuid: UUID){
val gameState = GameStateMessage(
uuid,
targetGameState.categoryIndex,
targetGameState.boardEntryIndex,
targetGameState.questionIndex,
targetGameState.questionLayerIndex,
)
messagingTemplate.convertAndSend("/topic/game/$uuid/questionlayer/selected", gameState)
}
@MessageMapping("/host/game/{uuid}/question/audio/play")
fun playAudio(@Payload audioMessage: GenericMessage, @DestinationVariable uuid: UUID){
messagingTemplate.convertAndSend("/topic/game/$uuid/question/audio/playing", GenericMessage("Playing audio"))
}
@MessageMapping("/host/game/{uuid}/question/audio/stop")
fun stopAudio(@Payload audioMessage: GenericMessage, @DestinationVariable uuid: UUID){
messagingTemplate.convertAndSend("/topic/game/$uuid/question/audio/stopped", GenericMessage("Playing audio"))
}
@MessageMapping("/host/game/{uuid}/question/reveal")
fun revealQuestion(@Payload gameState: GameStateMessage, @DestinationVariable uuid: UUID){
if(
gameState.categoryIndex == null ||
gameState.boardEntryIndex == null ||
gameState.questionIndex == null
){
throw InvalidPropertiesFormatException("Invalid gameSate to reveal question")
}
val game = gameRepository.findByUuid(uuid) ?: throw NoSuchElementException("Game with UUID $uuid not found")
val board = game.board
val question = board.categories[gameState.categoryIndex].boardEntries[gameState.boardEntryIndex].questions[gameState.questionIndex]
val questionDto = questionMapper.toDto(question)
messagingTemplate.convertAndSend("/topic/game/$uuid/question/revealed", questionDto)
}
@MessageExceptionHandler
@SendToUser("/error")
fun handleException(exception: Exception): GenericMessage{
log.error("Exception in GameEndpoint", exception)
return GenericMessage(exception.message ?: "Unknown error")
}
}
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.exception
open class NoMessageException(
override val message: String?,
override val cause: Throwable? = null,
) : RuntimeException(message, cause)
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.exception
open class StorageException(
override val message: String?,
override val cause: Throwable?
) : RuntimeException(message, cause)
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.exception
class StorageFileNotFoundException(
override val message: String?,
override val cause: Throwable?
) : StorageException(message, cause)
@@ -1,5 +1,6 @@
package at.eisibaer.jbear2.model package at.eisibaer.jbear2.model
import at.eisibaer.jbear2.model.enums.AnswerType
import jakarta.persistence.* import jakarta.persistence.*
@Entity @Entity
@@ -11,9 +12,13 @@ data class Answer(
@Column(name = "text", nullable = false, unique = false) @Column(name = "text", nullable = false, unique = false)
val text: String, val text: String,
@Enumerated
@Column(name = "answer_type", nullable = false, unique = false)
val answerType: AnswerType = AnswerType.TEXT,
@OneToOne @OneToOne
@JoinColumn(name = "fk_image_file", referencedColumnName = "id") @JoinColumn(name = "fk_image_file", referencedColumnName = "id")
val image: ImageFile?, var image: File?,
@OneToOne @OneToOne
@JoinColumn(name="fk_board_entry", referencedColumnName = "id") @JoinColumn(name="fk_board_entry", referencedColumnName = "id")
@@ -8,17 +8,20 @@ import jakarta.persistence.*
]) ])
data class Board( data class Board(
@OneToMany(mappedBy = "board") @OneToMany(mappedBy = "board", cascade = [CascadeType.ALL], orphanRemoval = true)
val categories: List<Category>, val categories: List<Category> = ArrayList(),
@Column(name = "board_name", nullable = false, unique = false) @Column(name = "board_name", nullable = false, unique = false)
val boardName: String, var boardName: String = "New Board",
@ManyToOne @ManyToOne
@JoinColumn(name="fk_owned_by", referencedColumnName = "id") @JoinColumn(name="fk_owned_by", referencedColumnName = "id")
val owner: User, var owner: User,
@Column(name = "points_are_title", nullable = false, unique = false)
var pointsAreTitle: Boolean = false,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
val id: Long? = null, var id: Long? = null,
) )
@@ -9,17 +9,20 @@ import jakarta.persistence.*
data class BoardEntry( data class BoardEntry(
@Column(name = "name", nullable = false, unique = false) @Column(name = "name", nullable = false, unique = false)
val name: String, var name: String,
@OneToMany(mappedBy = "boardEntry") @Column(name = "points", nullable = false, unique = false)
val questions: List<Question>, var points: Long,
@OneToOne @OneToMany(mappedBy = "boardEntry", cascade = [CascadeType.ALL], orphanRemoval = true)
val answer: Answer, val questions: List<Question> = ArrayList(),
@OneToOne(cascade = [CascadeType.ALL], orphanRemoval = true)
var answer: Answer? = null,
@ManyToOne @ManyToOne
@JoinColumn(name = "fk_category", referencedColumnName = "id") @JoinColumn(name = "fk_category", referencedColumnName = "id")
val category: Category?, var category: Category? = null,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@@ -9,17 +9,17 @@ import jakarta.persistence.*
data class Category ( data class Category (
@Column(name = "name", nullable = false, unique = false) @Column(name = "name", nullable = false, unique = false)
val name: String, var name: String,
@Column(name = "description", nullable = false, unique = false) @Column(name = "description", nullable = false, unique = false)
val description: String, var description: String,
@OneToMany(mappedBy = "category") @OneToMany(mappedBy = "category", cascade = [CascadeType.ALL], orphanRemoval = true)
val boardEntries: List<BoardEntry>, val boardEntries: List<BoardEntry> = ArrayList(),
@ManyToOne @ManyToOne
@JoinColumn(name = "fk_board", referencedColumnName = "id") @JoinColumn(name = "fk_board", referencedColumnName = "id")
val board: Board, var board: Board?,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@@ -1,5 +1,6 @@
package at.eisibaer.jbear2.model package at.eisibaer.jbear2.model
import at.eisibaer.jbear2.model.enums.FileType
import jakarta.persistence.* import jakarta.persistence.*
import java.util.UUID import java.util.UUID
@@ -7,7 +8,7 @@ import java.util.UUID
@Table(name = "image_files", indexes = [ @Table(name = "image_files", indexes = [
Index(name = "fk_owner_to_image_file", columnList = "fk_owned_by") Index(name = "fk_owner_to_image_file", columnList = "fk_owned_by")
]) ])
data class ImageFile ( data class File (
@Column(name = "uuid", nullable = false, unique = true) @Column(name = "uuid", nullable = false, unique = true)
val uuid: UUID, val uuid: UUID,
@@ -22,6 +23,9 @@ data class ImageFile (
@JoinColumn(name="fk_owned_by", referencedColumnName = "id") @JoinColumn(name="fk_owned_by", referencedColumnName = "id")
val owner: User, val owner: User,
@Column(name = "file_type", nullable = false, unique = false)
val fileType: FileType,
@OneToOne @OneToOne
val question: Question?, val question: Question?,
@@ -3,6 +3,7 @@ package at.eisibaer.jbear2.model
import jakarta.persistence.* import jakarta.persistence.*
import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.CreatedDate
import java.time.Instant import java.time.Instant
import java.util.*
@Entity @Entity
@Table(name = "games", indexes = [ @Table(name = "games", indexes = [
@@ -15,6 +16,9 @@ data class Game(
@Column(name = "invite_code", nullable = false, unique = true) @Column(name = "invite_code", nullable = false, unique = true)
val inviteCode: String, val inviteCode: String,
@Column(name = "uuid", nullable = false, unique = true)
val uuid: UUID,
@ManyToOne @ManyToOne
@JoinColumn(name = "fk_board", referencedColumnName = "id") @JoinColumn(name = "fk_board", referencedColumnName = "id")
val board: Board, val board: Board,
@@ -23,13 +27,9 @@ data class Game(
@JoinColumn(name="fk_host_user", referencedColumnName = "id") @JoinColumn(name="fk_host_user", referencedColumnName = "id")
val host: User, val host: User,
@OneToMany(mappedBy = "currentGame") @OneToMany(mappedBy = "currentGame", cascade = [CascadeType.ALL], orphanRemoval = true)
val players: List<Player>, val players: List<Player>,
@OneToOne
@JoinColumn(name="fk_player_currently_choosing", referencedColumnName = "id")
val currentlyChoosingPlayer: Player,
@ManyToMany @ManyToMany
@JoinTable( @JoinTable(
name = "answered_board_entries_in_games", name = "answered_board_entries_in_games",
@@ -38,12 +38,16 @@ data class Game(
) )
val alreadyAnsweredEntries: List<BoardEntry>, val alreadyAnsweredEntries: List<BoardEntry>,
@Column(name = "accepting_answers", nullable = false, unique = false) @OneToOne
val acceptingAnswers: Boolean? = false, @JoinColumn(name="fk_player_currently_choosing", referencedColumnName = "id")
val currentlyChoosingPlayer: Player?,
@CreatedDate @CreatedDate
@Column(name = "created_timestamp", nullable = false, unique = false) @Column(name = "created_timestamp", nullable = false, unique = false)
val createdTimestamp: Instant, val createdTimestamp: Instant? = Instant.now(),
@Column(name = "accepting_answers", nullable = false, unique = false)
val acceptingAnswers: Boolean? = false,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@@ -1,5 +1,6 @@
package at.eisibaer.jbear2.model package at.eisibaer.jbear2.model
import at.eisibaer.jbear2.model.enums.QuestionType
import jakarta.persistence.* import jakarta.persistence.*
@Entity @Entity
@@ -11,19 +12,22 @@ import jakarta.persistence.*
data class Question( data class Question(
@Column(name = "text", nullable = false, unique = false) @Column(name = "text", nullable = false, unique = false)
val text: String, var text: String,
@ManyToOne @Enumerated
@JoinColumn(name = "fk_question_type", referencedColumnName = "id") @Column(name = "question_type", nullable = false, unique = false)
val questionType: QuestionType, var questionType: QuestionType = QuestionType.TEXT,
@Column(name = "font_scaling", nullable = false, unique = false)
var fontScaling: Int,
@OneToOne @OneToOne
@JoinColumn(name = "fk_image", referencedColumnName = "id") @JoinColumn(name = "fk_image", referencedColumnName = "id")
val image: ImageFile?, var image: File?,
@ManyToOne @ManyToOne
@JoinColumn(name = "fk_board_entry", referencedColumnName = "id") @JoinColumn(name = "fk_board_entry", referencedColumnName = "id")
val boardEntry: BoardEntry?, var boardEntry: BoardEntry?,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@@ -1,21 +0,0 @@
package at.eisibaer.jbear2.model
import jakarta.persistence.*
@Entity
@Table(name = "question_types")
data class QuestionType(
@Column(name = "title", nullable = false, unique = true)
val title: String,
@Column(name = "description", nullable = false, unique = true)
val description: String,
@Column(name = "active", nullable = false, unique = false)
val active: Boolean,
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
val id: Long? = null,
)
@@ -20,7 +20,7 @@ data class User(
@OneToOne @OneToOne
@JoinColumn(name = "fk_profile_picture", referencedColumnName = "id") @JoinColumn(name = "fk_profile_picture", referencedColumnName = "id")
var profilePicture: ImageFile?, var profilePicture: File?,
@Id @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@@ -0,0 +1,8 @@
package at.eisibaer.jbear2.model.enums
enum class AnswerType {
TEXT,
IMAGE,
AUDIO,
LOCATION;
}
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.model.enums
enum class FileType{
IMAGE,
AUDIO,
}
@@ -0,0 +1,8 @@
package at.eisibaer.jbear2.model.enums
enum class QuestionType {
TEXT,
IMAGE,
AUDIO,
LOCATION;
}
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.Answer
import org.springframework.data.jpa.repository.JpaRepository
interface AnswerRepository : JpaRepository<Answer, Long>
@@ -0,0 +1,16 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.Board
import at.eisibaer.jbear2.model.User
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface BoardRepository : JpaRepository<Board, Long> {
fun findByIdAndOwner(id: Long, user: User): Board?
fun findAllByOwner(owner: User): List<Board>
fun findFirstByOwnerOrderByBoardName(owner: User): Board?
}
@@ -0,0 +1,12 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.File
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.UUID
@Repository
interface FileRepository : JpaRepository<File, Long> {
fun findByUuid(uuid: UUID): File?;
}
@@ -0,0 +1,12 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.Game
import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID
interface GameRepository : JpaRepository<Game, Long> {
fun findByInviteCode(inviteCode: String): Game?
fun findByUuid(uuid: UUID): Game?
}
@@ -0,0 +1,8 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.Player
import org.springframework.data.jpa.repository.JpaRepository
interface PlayerRepository : JpaRepository<Player, Long> {
}
@@ -0,0 +1,6 @@
package at.eisibaer.jbear2.repository
import at.eisibaer.jbear2.model.Question
import org.springframework.data.jpa.repository.JpaRepository
interface QuestionRepository : JpaRepository<Question, Long>
@@ -8,7 +8,7 @@ import java.util.*
@Repository @Repository
interface UserRepository : JpaRepository<User, Long> { interface UserRepository : JpaRepository<User, Long> {
fun findUserByUsername(username: String): Optional<User>; fun findUserByUsername(username: String): User?;
fun existsByUsername(username: String): Boolean; fun existsByUsername(username: String): Boolean;
} }
@@ -1,6 +1,7 @@
package at.eisibaer.jbear2.security package at.eisibaer.jbear2.security
import at.eisibaer.jbear2.config.ApplicationProperties import at.eisibaer.jbear2.config.ApplicationProperties
import at.eisibaer.jbear2.repository.UserRepository
import jakarta.servlet.FilterChain import jakarta.servlet.FilterChain
import jakarta.servlet.ServletException import jakarta.servlet.ServletException
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
@@ -10,8 +11,8 @@ import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.ProviderManager
import org.springframework.security.authentication.dao.DaoAuthenticationProvider import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.core.userdetails.UserDetailsService
@@ -29,30 +30,28 @@ import java.util.function.Supplier
@Configuration @Configuration
@EnableMethodSecurity @EnableMethodSecurity
class SecurityConfiguration( class SecurityConfiguration(
private val userDetailService: UserDetailsService, private val userRepository: UserRepository,
private val unauthorizedHandler: AuthFilter, private val unauthorizedHandler: AuthFilter,
private val applicationProperties: ApplicationProperties private val applicationProperties: ApplicationProperties
) { ) {
final val log: Logger = LoggerFactory.getLogger(SecurityConfiguration::class.java); final val log: Logger = LoggerFactory.getLogger(SecurityConfiguration::class.java)
@Bean @Bean
fun securityFilterChain(httpSecurity: HttpSecurity): SecurityFilterChain { fun securityFilterChain(httpSecurity: HttpSecurity): SecurityFilterChain {
return addCsrfConfig(httpSecurity) return addCsrfConfig(httpSecurity)
.authorizeHttpRequests { config -> .authorizeHttpRequests { config ->
config config
.requestMatchers("/api/auth/*").permitAll()
.requestMatchers("/api/user/**").authenticated() .requestMatchers("/api/user/**").authenticated()
.requestMatchers("/**").permitAll() .requestMatchers("/**").permitAll()
} }
.authenticationProvider(authenticationProvider())
.addFilterBefore(unauthorizedHandler, UsernamePasswordAuthenticationFilter::class.java) .addFilterBefore(unauthorizedHandler, UsernamePasswordAuthenticationFilter::class.java)
.build() .build()
} }
private fun addCsrfConfig(httpSecurity: HttpSecurity): HttpSecurity{ private fun addCsrfConfig(httpSecurity: HttpSecurity): HttpSecurity{
if( applicationProperties.test ){ if( applicationProperties.test ){
httpSecurity.csrf{ config -> config.disable()}; httpSecurity.csrf{ config -> config.disable()}
} else { } else {
httpSecurity.csrf { config -> httpSecurity.csrf { config ->
config config
@@ -61,7 +60,7 @@ class SecurityConfiguration(
} }
.addFilterAfter(CsrfCookieFilter(), BasicAuthenticationFilter::class.java) .addFilterAfter(CsrfCookieFilter(), BasicAuthenticationFilter::class.java)
} }
return httpSecurity; return httpSecurity
} }
class SpaCsrfTokenRequestHandler : CsrfTokenRequestAttributeHandler() { class SpaCsrfTokenRequestHandler : CsrfTokenRequestAttributeHandler() {
@@ -108,21 +107,18 @@ class SecurityConfiguration(
@Bean @Bean
fun passwordEncoder() : PasswordEncoder { fun passwordEncoder() : PasswordEncoder {
return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8(); return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8()
} }
@Bean @Bean
fun authenticationProvider(): DaoAuthenticationProvider{ fun authenticationProvider(): AuthenticationManager {
val authProvider: DaoAuthenticationProvider = DaoAuthenticationProvider() val authProvider = DaoAuthenticationProvider(userDetailService())
authProvider.setPasswordEncoder(passwordEncoder())
authProvider.setUserDetailsService(userDetailService) return ProviderManager(authProvider)
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
} }
@Bean @Bean
fun authenticationManager(authConfig: AuthenticationConfiguration): AuthenticationManager{ fun userDetailService(): UserDetailsService {
return authConfig.authenticationManager; return UserDetailServiceImpl(userRepository)
} }
} }
@@ -16,13 +16,17 @@ class UserDetailServiceImpl(
): UserDetailsService { ): UserDetailsService {
override fun loadUserByUsername(username: String?): UserDetailsImpl { override fun loadUserByUsername(username: String?): UserDetailsImpl {
val user: User = userRepository.findUserByUsername( username ?: "" ).orElseThrow { UsernameNotFoundException("User not found by username \"$username\"") } if( username == null ){
throw UsernameNotFoundException("User not found by username \"$username\"")
}
val user: User = userRepository.findUserByUsername( username )
?: throw UsernameNotFoundException("User not found by username \"$username\"")
return UserDetailsImpl( return UserDetailsImpl(
user.id!!, user.id!!,
user.username, user.username,
user.password, user.password,
user.profilePicture?.filename, user.profilePicture?.filename,
); )
} }
} }
@@ -0,0 +1,16 @@
package at.eisibaer.jbear2.service
import at.eisibaer.jbear2.dto.board.BoardDto
import at.eisibaer.jbear2.model.User
import org.springframework.http.ResponseEntity
import org.springframework.web.multipart.MultipartFile
interface BoardService {
fun getBoardsByUser( user: User ): ResponseEntity<List<BoardDto>?>
fun getBoardByUserAndId( user: User, boardId: Long ): ResponseEntity<BoardDto?>
fun saveBoardToUser( user: User, boardDto: BoardDto, files: List<MultipartFile> ): ResponseEntity<BoardDto>
fun deleteBoardOfUser( user: User, boardId: Long ): ResponseEntity<Unit>
}
@@ -0,0 +1,100 @@
package at.eisibaer.jbear2.service
import at.eisibaer.jbear2.dto.board.BoardDto
import at.eisibaer.jbear2.model.Board
import at.eisibaer.jbear2.model.User
import at.eisibaer.jbear2.repository.BoardRepository
import at.eisibaer.jbear2.repository.FileRepository
import at.eisibaer.jbear2.repository.UserRepository
import at.eisibaer.jbear2.service.mapper.BoardMapper
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.multipart.MultipartFile
@Service
class BoardServiceImpl (
private val fileService: FileService,
private val boardRepository: BoardRepository,
private val userRepository: UserRepository,
private val fileRepository: FileRepository,
private val boardMapper: BoardMapper,
) : BoardService {
val log: Logger = LoggerFactory.getLogger(BoardServiceImpl::class.java)
@Transactional
override fun getBoardsByUser(user: User): ResponseEntity<List<BoardDto>?> {
val boards = boardRepository.findAllByOwner(user)
return ResponseEntity.ok(boardMapper.toDto(boards))
}
@Transactional
override fun getBoardByUserAndId(user: User, boardId: Long): ResponseEntity<BoardDto?> {
val board = boardRepository.findByIdAndOwner(boardId, user) ?: return ResponseEntity.status(404).build()
return ResponseEntity.ok(boardMapper.toDto(board))
}
@Transactional
override fun saveBoardToUser( user: User, boardDto: BoardDto, files: List<MultipartFile>): ResponseEntity<BoardDto> {
val board = if( boardDto.id == null ){
Board(owner = user)
} else {
boardRepository.findByIdAndOwner(boardDto.id, user) ?: throw NoSuchElementException("Board not found for user " + user.username)
}
boardMapper.mapToEntity(board, boardDto, user, userRepository, fileRepository)
val savedBoard: Board
try {
savedBoard = boardRepository.save(board)
} catch (ex: Exception) {
log.error(ex.message, ex)
return ResponseEntity.badRequest().build()
}
try{
fileService.saveFiles(files, user, savedBoard)
} catch (ex: Exception) {
log.error(ex.message, ex)
return ResponseEntity.badRequest().build()
}
return ResponseEntity.ok(boardMapper.toDto(savedBoard))
}
override fun deleteBoardOfUser(user: User, boardId: Long): ResponseEntity<Unit> {
val board = boardRepository.findByIdAndOwner(boardId, user) ?: return ResponseEntity.status(HttpStatus.NOT_FOUND).build()
boardRepository.deleteById( boardId )
//TODO Delete Images
return ResponseEntity.ok().build()
}
private fun deleteFilesOfBoard(board: Board) {
try {
for (category in board.categories) {
for (boardEntry in category.boardEntries) {
if (boardEntry.answer != null && boardEntry.answer!!.image != null) {
fileService.deleteFile(boardEntry.answer!!.image!!)
}
for (question in boardEntry.questions) {
if (question.image != null) {
fileService.deleteFile(question.image!!)
}
}
}
}
} catch (exception: Exception) {
log.error("Error occured",exception) //TODO
}
}
}
@@ -0,0 +1,20 @@
package at.eisibaer.jbear2.service
import at.eisibaer.jbear2.model.Board
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.model.User
import org.springframework.core.io.Resource
import org.springframework.web.multipart.MultipartFile
import java.util.UUID
interface FileService {
fun saveFiles(files: List<MultipartFile>, owner: User, board: Board)
fun saveFile(file: MultipartFile, owner: User, board: Board): File
fun getFile(file: File): Resource
fun getFile(fileUUID: UUID): Resource
fun deleteFile(file: File): Resource
fun deleteFile(fileUUID: UUID): Resource
}
@@ -0,0 +1,112 @@
package at.eisibaer.jbear2.service
import at.eisibaer.jbear2.model.*
import at.eisibaer.jbear2.model.enums.FileType
import at.eisibaer.jbear2.repository.AnswerRepository
import at.eisibaer.jbear2.repository.FileRepository
import at.eisibaer.jbear2.repository.QuestionRepository
import lombok.extern.slf4j.Slf4j
import org.apache.tomcat.util.http.fileupload.InvalidFileNameException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.core.io.Resource
import org.springframework.stereotype.Service
import org.springframework.util.InvalidMimeTypeException
import org.springframework.web.multipart.MultipartFile
import java.security.MessageDigest
import java.util.*
@Slf4j
@Service
class FileServiceImpl (
val fileRepository: FileRepository,
val answerRepository: AnswerRepository,
val questionRepository: QuestionRepository,
val storageService: StorageService,
) : FileService {
val log: Logger = LoggerFactory.getLogger(FileServiceImpl::class.java)
override fun saveFiles(files: List<MultipartFile>, owner: User, board: Board) {
val digest: MessageDigest = MessageDigest.getInstance("SHA-256")
for(file in files) {
if( file.originalFilename == null ){
throw InvalidFileNameException(file.originalFilename, "No filename given")
}
val associatedEntries = file.originalFilename!!.split("-")
if( associatedEntries.size != 3) {
throw InvalidFileNameException(file.name, "Invalid index name")
}
val boardEntry = board.categories[associatedEntries[0].toInt()].boardEntries[associatedEntries[1].toInt()]
var question: Question? = null
var answer: Answer? = null
if(associatedEntries[2] == "answer"){
answer = boardEntry.answer
} else {
question = boardEntry.questions[associatedEntries[2].toInt()]
}
val uuid = UUID.randomUUID()
val filename = uuid.toString() + getExtension(file)
storageService.storeFile(file, filename)
log.debug("File stored")
val newFile = File(
uuid,
filename,
Base64.getEncoder().encodeToString(digest.digest(file.bytes)),
owner,
if (file.contentType.orEmpty().startsWith("image")) FileType.IMAGE else FileType.AUDIO,
question,
answer,
)
val savedFile: File = fileRepository.save(newFile)
if(associatedEntries[2] == "answer"){
if( answer != null ){
if( savedFile.fileType == FileType.IMAGE ) {
answer.image = savedFile
}
answerRepository.save(answer)
}
} else if( question != null ){
if( savedFile.fileType == FileType.IMAGE ) {
question.image = savedFile
}
questionRepository.save(question)
}
}
return
}
override fun saveFile(file: MultipartFile, owner: User, board: Board): File {
TODO("Not yet implemented")
}
private fun getExtension(file: MultipartFile): String {
return when (file.contentType) {
"image/jpeg" -> ".jpg"
"image/png" -> ".png"
"image/avif" -> ".avif"
"image/webp" -> ".webp"
else -> throw InvalidMimeTypeException(file.contentType ?: "unknown", "MIME Type not accepted")
}
}
override fun getFile(file: File): Resource {
TODO("Not yet implemented")
}
override fun getFile(fileUUID: UUID): Resource {
TODO("Not yet implemented")
}
override fun deleteFile(file: File): Resource {
TODO("Not yet implemented")
}
override fun deleteFile(fileUUID: UUID): Resource {
TODO("Not yet implemented")
}
}
@@ -0,0 +1,91 @@
package at.eisibaer.jbear2.service
import at.eisibaer.jbear2.config.ApplicationProperties
import at.eisibaer.jbear2.exception.StorageException
import at.eisibaer.jbear2.exception.StorageFileNotFoundException
import jakarta.annotation.PostConstruct
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.core.io.Resource
import org.springframework.core.io.UrlResource
import org.springframework.stereotype.Service
import org.springframework.util.FileSystemUtils
import org.springframework.web.multipart.MultipartFile
import java.io.IOException
import java.net.MalformedURLException
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
@Service
class FileSystemStorageService(
val applicationProperties: ApplicationProperties,
) : StorageService {
val log: Logger = LoggerFactory.getLogger(FileSystemStorageService::class.java)
lateinit var rootLocation: Path
@PostConstruct
fun init(){
val location = applicationProperties.storage.fs.location
if( location.trim().isEmpty() ){
throw StorageException("File upload location can not be Empty", null)
}
rootLocation = Paths.get(location)
}
override fun storeFile(file: MultipartFile, filename: String) {
storeMultipartFile(file, filename)
}
override fun storeFiles(files: List<Pair<MultipartFile, String>>) {
for( file in files ){
storeMultipartFile(file.first, file.second)
}
}
override fun getFile(filename: String): Resource {
try {
val file: Path = rootLocation.resolve(filename)
val resource: Resource = UrlResource(file.toUri())
if (resource.exists() || resource.isReadable) {
return resource
} else {
throw StorageFileNotFoundException("Could not read file: $filename", null)
}
} catch (e: MalformedURLException) {
throw StorageFileNotFoundException("Could not read file: $filename", e)
}
}
override fun deleteFile(filename: String) {
FileSystemUtils.deleteRecursively(rootLocation.resolve(filename))
}
private fun storeMultipartFile(file: MultipartFile, filename: String){
try {
if (file.isEmpty) {
throw StorageException("Failed to store empty file.", null)
}
val destinationFile: Path = rootLocation
.resolve(Paths.get(filename))
.normalize()
.toAbsolutePath()
if (destinationFile.parent != rootLocation.toAbsolutePath()) {
// This is a security check
throw StorageException("Cannot store file outside current directory.", null)
}
file.inputStream.use { inputStream ->
Files.copy(
inputStream, destinationFile,
StandardCopyOption.REPLACE_EXISTING
)
}
} catch (e: IOException) {
throw StorageException("Failed to store file.", e)
}
}
}
@@ -0,0 +1,15 @@
package at.eisibaer.jbear2.service
import org.springframework.core.io.Resource
import org.springframework.web.multipart.MultipartFile
interface StorageService {
fun storeFile(file: MultipartFile, filename: String)
fun storeFiles(files: List<Pair<MultipartFile, String>>)
fun getFile(filename: String): Resource
fun deleteFile(filename: String)
}
@@ -0,0 +1,43 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.board.AnswerDto
import at.eisibaer.jbear2.model.Answer
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.model.enums.AnswerType
import at.eisibaer.jbear2.repository.FileRepository
import org.mapstruct.Context
import org.mapstruct.Mapper
import java.util.*
@Mapper
abstract class AnswerMapper {
abstract fun toDto(e: Answer): AnswerDto
abstract fun toDto(e: List<Answer>): List<AnswerDto>
abstract fun toEntity(d: AnswerDto, @Context fileRepository: FileRepository): Answer
abstract fun toEntity(d: List<AnswerDto>, @Context fileRepository: FileRepository): List<Answer>
fun map(file: File?): String{
return file?.uuid.toString()
}
fun map(imageUuid: String?, @Context fileRepository: FileRepository): File? {
return if( imageUuid == null ) {
null
} else {
try{
fileRepository.findByUuid(UUID.fromString(imageUuid))
} catch ( illegalArgumentException: IllegalArgumentException ){
null
}
}
}
fun map(type: AnswerType): Int {
return type.ordinal;
}
fun map(value: Int): AnswerType {
return AnswerType.entries[value];
}
}
@@ -0,0 +1,42 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.board.BoardEntryDto
import at.eisibaer.jbear2.model.BoardEntry
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.repository.FileRepository
import org.mapstruct.AfterMapping
import org.mapstruct.Context
import org.mapstruct.Mapper
import org.mapstruct.MappingTarget
import java.util.*
@Mapper(uses = [QuestionMapper::class,AnswerMapper::class])
abstract class BoardEntryMapper {
abstract fun toDto(e: BoardEntry): BoardEntryDto
abstract fun toDto(e: List<BoardEntry>): List<BoardEntryDto>
abstract fun toEntity(d: BoardEntryDto, @Context fileRepository: FileRepository): BoardEntry
abstract fun toEntity(d: List<BoardEntryDto>, @Context fileRepository: FileRepository): List<BoardEntry>
abstract fun mapToEntity(d: BoardEntryDto, @MappingTarget e: BoardEntry, @Context fileRepository: FileRepository)
fun map(file: File): String{
return file.uuid.toString()
}
fun map(imageUuid: String?, @Context fileRepository: FileRepository): File? {
return if( imageUuid == null ) {
null
} else {
fileRepository.findByUuid(UUID.fromString(imageUuid))
}
}
@AfterMapping
fun addBoardEntryToQuestion(source: BoardEntryDto, @MappingTarget target: BoardEntry): BoardEntry {
for( question in target.questions ){
question.boardEntry = target
}
return target
}
}
@@ -0,0 +1,40 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.board.BoardDto
import at.eisibaer.jbear2.model.Board
import at.eisibaer.jbear2.model.User
import at.eisibaer.jbear2.repository.FileRepository
import at.eisibaer.jbear2.repository.UserRepository
import org.mapstruct.*
@Mapper(uses = [QuestionMapper::class,AnswerMapper::class,BoardEntryMapper::class,CategoryMapper::class])
abstract class BoardMapper {
abstract fun toDto(e: Board): BoardDto
abstract fun toDto(e: List<Board>): List<BoardDto>
@Mappings(value = [
Mapping(target = "owner", source = "ownerUser"),
Mapping(target = "id", source = "d.id"),
])
abstract fun toEntity(d: BoardDto, ownerUser: User, @Context userRepository: UserRepository, @Context fileRepository: FileRepository): Board
abstract fun toEntity(d: List<BoardDto>, ownerUser: User, @Context userRepository: UserRepository, @Context fileRepository: FileRepository): ArrayList<Board>
@Mappings(value = [
Mapping(target = "owner", source = "ownerUser"),
Mapping(target = "id", source = "d.id"),
])
abstract fun mapToEntity(@MappingTarget board: Board, d: BoardDto, ownerUser: User, @Context userRepository: UserRepository, @Context fileRepository: FileRepository): Board
fun map(owner: User): String{
return owner.username
}
@AfterMapping
fun addBoardToCategory(source: BoardDto, @MappingTarget target: Board ): Board{
for( category in target.categories ){
category.board = target
}
return target
}
}
@@ -0,0 +1,40 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.board.CategoryDto
import at.eisibaer.jbear2.model.Category
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.repository.FileRepository
import org.mapstruct.AfterMapping
import org.mapstruct.Context
import org.mapstruct.Mapper
import org.mapstruct.MappingTarget
import java.util.*
@Mapper(uses = [QuestionMapper::class,AnswerMapper::class,BoardEntryMapper::class])
abstract class CategoryMapper {
abstract fun toDto(e: Category): CategoryDto
abstract fun toDto(e: List<Category>): List<CategoryDto>
abstract fun toEntity(d: CategoryDto, @Context fileRepository: FileRepository, @Context boardEntryMapper: BoardEntryMapper): Category
abstract fun toEntity(d: List<CategoryDto>, @Context fileRepository: FileRepository, @Context boardEntryMapper: BoardEntryMapper): List<Category>
fun map(file: File): String{
return file.uuid.toString()
}
fun map(imageUuid: String?, @Context fileRepository: FileRepository): File? {
return if( imageUuid == null ) {
null
} else {
fileRepository.findByUuid(UUID.fromString(imageUuid))
}
}
@AfterMapping
fun addCategoryToBoardEntry(source: CategoryDto, @MappingTarget target: Category): Category {
for( boardEntry in target.boardEntries ){
boardEntry.category = target
}
return target
}
}
@@ -0,0 +1,9 @@
package at.eisibaer.jbear2.service.mapper
interface EntityMapper<D, E> {
fun toDto(e: E): D;
fun toDto(e: List<E>): List<D>;
fun toEntity(d: D): E;
fun toEntity(d: List<D>): List<E>;
}
@@ -0,0 +1,8 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.game.GameDto
import at.eisibaer.jbear2.model.Game
import org.mapstruct.Mapper
@Mapper(uses = [PlayerMapper::class])
interface GameMapper : EntityMapper<GameDto, Game>
@@ -0,0 +1,26 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.repository.FileRepository
import org.mapstruct.Context
import org.mapstruct.Mapper
import java.util.*
@Mapper
abstract class ImageMapper {
fun toEntity(d: String, @Context fileRepository: FileRepository): File? {
return fileRepository.findByUuid(UUID.fromString(d));
}
fun toDto(e: File): String {
return e.uuid.toString();
}
fun toDto(e: List<File>): List<String>{
return e.map { toDto(it) }
}
fun toEntity(d: List<String>, @Context fileRepository: FileRepository): List<File?>{
return d.map { toEntity(it, fileRepository) }
}
}
@@ -0,0 +1,10 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.game.PlayerDto
import at.eisibaer.jbear2.model.Player
import org.mapstruct.Mapper
@Mapper
interface PlayerMapper : EntityMapper<PlayerDto, Player> {
}
@@ -0,0 +1,43 @@
package at.eisibaer.jbear2.service.mapper
import at.eisibaer.jbear2.dto.board.QuestionDto
import at.eisibaer.jbear2.model.File
import at.eisibaer.jbear2.model.Question
import at.eisibaer.jbear2.model.enums.QuestionType
import at.eisibaer.jbear2.repository.FileRepository
import org.mapstruct.Context
import org.mapstruct.Mapper
import java.util.UUID
@Mapper
abstract class QuestionMapper {
abstract fun toDto(e: Question): QuestionDto;
abstract fun toDto(e: List<Question>): List<QuestionDto>;
abstract fun toEntity(d: QuestionDto, @Context fileRepository: FileRepository): Question;
abstract fun toEntity(d: List<QuestionDto>, @Context fileRepository: FileRepository): List<Question>;
fun map(file: File?): String?{
return file?.uuid.toString();
}
fun map(imageUuid: String?, @Context fileRepository: FileRepository): File? {
return if( imageUuid == null ) {
null
} else {
try{
fileRepository.findByUuid(UUID.fromString(imageUuid))
} catch ( illegalArgumentException: IllegalArgumentException ){
null
}
}
}
fun map(type: QuestionType): Int {
return type.ordinal;
}
fun map(value: Int): QuestionType {
return QuestionType.entries[value];
}
}
@@ -2,4 +2,5 @@ package at.eisibaer.jbear2.util
object Constants { object Constants {
const val STR_SESSION_USER_KEY = "user" const val STR_SESSION_USER_KEY = "user"
const val INVITE_CODE_LENGTH = 8
} }
@@ -0,0 +1,17 @@
package at.eisibaer.jbear2.util
import java.security.SecureRandom
class RandomString{
companion object{
val AB: String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
val rnd: SecureRandom = SecureRandom()
fun ofLength(len: Int): String {
val sb = StringBuilder(len)
for (i in 0 until len) sb.append(AB[rnd.nextInt(AB.length)])
return sb.toString()
}
}
}
@@ -3,6 +3,9 @@ logging:
at: at:
eisibaer: eisibaer:
jbear2: "DEBUG" jbear2: "DEBUG"
# org:
# springframework:
# security: "TRACE"
spring: spring:
datasource: datasource:
url: jdbc:postgresql://${PG_HOST}:${PG_PORT}/jeobeardy?currentSchema=jeobeardy-app url: jdbc:postgresql://${PG_HOST}:${PG_PORT}/jeobeardy?currentSchema=jeobeardy-app
+23 -4
View File
@@ -11,13 +11,32 @@ spring:
dialect: org.hibernate.dialect.PostgreSQLDialect dialect: org.hibernate.dialect.PostgreSQLDialect
default-schema: jeobeardy-app default-schema: jeobeardy-app
open-in-view: false open-in-view: false
docker: servlet:
compose: multipart:
lifecycle-management: start-only max-file-size: 1MB
max-request-size: 40MB
session:
store-type: jdbc
jdbc:
initialize-schema: always
# redis:
# flush-mode: on_save
# namespace: spring:session
# data:
# redis:
# host: localhost
# password:
# port: 6379
server: server:
address: localhost address: localhost
port: 8008 port: 8008
# servlet:
# session:
# timeout:
application: application:
cors-allowed-methods: ["GET", "POST", "DELETE", "OPTIONS"] cors-allowed-methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
storage:
fs:
location: "files"
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

@@ -1,5 +0,0 @@
@charset "UTF-8";.home-player-join-row[data-v-6c838f03]{background-image:url(/assets/OldInGameBlurredRotated-Bc8vmN0_.jpeg);background-repeat:no-repeat;background-size:cover}.preserve-breaks{white-space:preserve-breaks}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media (min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#e86a92;border-color:#e86a92;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f4b5c9'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.was-validated .form-control:valid,.form-control.is-valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' dLine truncated
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-primary: #e86a92;--bs-secondary: #3e92cc;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #edf2f4;--bs-dark: #2b2d42;--bs-gray: #adb5bd;--bs-dark-accented: #252638;--bs-rich-black: #2d3543;--bs-primary-rgb: 232, 106, 146;--bs-secondary-rgb: 62, 146, 204;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 237, 242, 244;--bs-dark-rgb: 43, 45, 66;--bs-gray-rgb: 173, 181, 189;--bs-dark-accented-rgb: 37, 38, 56;--bs-rich-black-rgb: 45, 53, 67;--bs-primary-text-emphasis: #5d2a3a;--bs-secondary-text-emphasis: #193a52;--bs-success-text-emphasis: #0a3622;--bs-info-text-emphasis: #055160;--bs-warning-text-emphasis: #664d03;--bs-danger-text-emphasis: #58151c;--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: #fae1e9;--bs-secondary-bg-subtle: #d8e9f5;--bs-success-bg-subtle: #d1e7dd;--bs-info-bg-subtle: #cff4fc;--bs-warning-bg-subtle: #fff3cd;--bs-danger-bg-subtle: #f8d7da;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #f6c3d3;--bs-secondary-border-subtle: #b2d3eb;--bs-success-border-subtle: #a3cfbb;--bs-info-border-subtle: #9eeaf9;--bs-warning-border-subtle: #ffe69c;--bs-danger-border-subtle: #f1aeb5;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #edf2f4;--bs-body-bg-rgb: 237, 242, 244;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, .75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #d5dadc;--bs-secondary-bg-rgb: 213, 218, 220;--bs-tertiary-color: rgba(33, 37, 41, .5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #e86a92;--bs-link-color-rgb: 232, 106, 146;--bs-link-decoration: underline;--bs-link-hover-color: #ba5575;--bs-link-hover-color-rgb: 186, 85, 117;--bs-code-color: #d63384;--bs-highlight-color: #212529;--bs-highlight-bg: #fff3cd;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, .175);--bs-border-radius: .375rem;--bs-border-radius-sm: .25rem;--bs-border-radius-lg: .5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width: .25rem;--bs-focus-ring-opacity: .25;--bs-focus-ring-color: rgba(232, 106, 146, .25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #2b2d42;--bs-body-bg-rgb: 43, 45, 66;--bs-emphasis-color: #fff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, .75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #252638;--bs-secondary-bg-rgb: 37, 38, 56;--bs-tertiary-color: rgba(222, 226, 230, .5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #f1a6be;--bs-secondary-text-emphasis: #8bbee0;--bs-success-text-emphasis: #75b798;--bs-info-text-emphasis: #6edff6;--bs-warning-text-emphasis: #ffda6a;--bs-danger-text-emphasis: #ea868f;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #2e151d;--bs-secondary-bg-subtle: #0c1d29;--bs-success-bg-subtle: #051b11;--bs-info-bg-subtle: #032830;--bs-warning-bg-subtle: #332701;--bs-danger-bg-Line truncated
@@ -0,0 +1,5 @@
@charset "UTF-8";.pfp-sizing[data-v-6ff68e56]{width:2.5rem;height:2.5rem;object-fit:cover}.home-player-join-row[data-v-9fe00568]{background-image:url(/assets/OldInGameBlurredRotated-Bc8vmN0_.jpeg);background-repeat:no-repeat;background-size:cover}.board-card-max-height[data-v-b4bbf48f]{max-height:20%}.object-contain[data-v-738ecf74]{object-fit:contain}.spinny-spin[data-v-f408fdec]{animation-name:spinny-f408fdec;animation-duration:1.5s;animation-iteration-count:infinite;animation-timing-function:linear}@keyframes spinny-f408fdec{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spinny-size[data-v-f408fdec]{max-width:6.66em;max-height:6.66em}.draggable-ghost[data-v-c5bb5ee8],.draggable-ghost[data-v-537d158e],.draggable-ghost[data-v-8e3146bf],.draggable-ghost[data-v-f103494e],.draggable-ghost[data-v-376407ed]{opacity:.75}/*!
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/.preserve-breaks{white-space:preserve-breaks}.pointer{cursor:pointer}.cursor-move{cursor:move}:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-primary: #e86a92;--bs-secondary: #3e92cc;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #edf2f4;--bs-dark: #2b2d42;--bs-gray: #adb5bd;--bs-dark-accented: #252638;--bs-rich-black: #2d3543;--bs-primary-rgb: 232, 106, 146;--bs-secondary-rgb: 62, 146, 204;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 237, 242, 244;--bs-dark-rgb: 43, 45, 66;--bs-gray-rgb: 173, 181, 189;--bs-dark-accented-rgb: 37, 38, 56;--bs-rich-black-rgb: 45, 53, 67;--bs-primary-text-emphasis: #5d2a3a;--bs-secondary-text-emphasis: #193a52;--bs-success-text-emphasis: #0a3622;--bs-info-text-emphasis: #055160;--bs-warning-text-emphasis: #664d03;--bs-danger-text-emphasis: #58151c;--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: #fae1e9;--bs-secondary-bg-subtle: #d8e9f5;--bs-success-bg-subtle: #d1e7dd;--bs-info-bg-subtle: #cff4fc;--bs-warning-bg-subtle: #fff3cd;--bs-danger-bg-subtle: #f8d7da;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #f6c3d3;--bs-secondary-border-subtle: #b2d3eb;--bs-success-border-subtle: #a3cfbb;--bs-info-border-subtle: #9eeaf9;--bs-warning-border-subtle: #ffe69c;--bs-danger-border-subtle: #f1aeb5;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #edf2f4;--bs-body-bg-rgb: 237, 242, 244;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, .75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #d5dadc;--bs-secondary-bg-rgb: 213, 218, 220;--bs-tertiary-color: rgba(33, 37, 41, .5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #e86a92;--bs-link-color-rgb: 232, 106, 146;--bs-link-decoration: underline;--bs-link-hover-color: #ba5575;--bs-link-hover-color-rgb: 186, 85, 117;--bs-code-color: #d63384;--bs-highlight-color: #212529;--bs-highlight-bg: #fff3cd;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, .175);--bs-border-radius: .375rem;--bs-border-radius-sm: .25rem;--bs-border-radius-lg: .5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width: .25rem;--bs-focus-ring-opacity: .25;--bs-focus-ring-color: rgba(232, 106, 146, .25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #2b2d42;--bs-body-bg-rgb: 43, 45, 66;--bs-emphasis-color: #fff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, .75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #252638;--bs-secondary-bg-rgb: 37, 38, 56;--bs-tertiary-color: rgba(222, 226, 230, .5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #f1a6be;--bs-secondary-text-emphasis: #8bbee0;--bs-success-text-emphasis: #75b798;--bs-info-text-emphasis: #6edff6;--bs-warning-text-emphasis: #ffda6a;--bs-danger-text-emphasis: #ea868f;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #2e151d;--bs-secondary-bg-subtle: #0c1d29;--bs-success-bLine truncated
@@ -0,0 +1,821 @@
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(s){if(s.ep)return;s.ep=!0;const o=n(s);fetch(s.href,o)}})();/**
* @vue/shared v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**//*! #__NO_SIDE_EFFECTS__ */function ju(e,t){const n=new Set(e.split(","));return r=>n.has(r)}const ze={},Fs=[],rn=()=>{},vy=()=>!1,Ja=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Bu=e=>e.startsWith("onUpdate:"),mt=Object.assign,Wu=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},by=Object.prototype.hasOwnProperty,Pe=(e,t)=>by.call(e,t),de=Array.isArray,Vs=e=>fi(e)==="[object Map]",lo=e=>fi(e)==="[object Set]",dd=e=>fi(e)==="[object Date]",Ae=e=>typeof e=="function",pt=e=>typeof e=="string",Xn=e=>typeof e=="symbol",qe=e=>e!==null&&typeof e=="object",Bp=e=>(qe(e)||Ae(e))&&Ae(e.then)&&Ae(e.catch),Wp=Object.prototype.toString,fi=e=>Wp.call(e),yy=e=>fi(e).slice(8,-1),zp=e=>fi(e)==="[object Object]",zu=e=>pt(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Lo=ju(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Za=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ey=/-(\w)/g,yn=Za(e=>e.replace(Ey,(t,n)=>n?n.toUpperCase():"")),wy=/\B([A-Z])/g,Vr=Za(e=>e.replace(wy,"-$1").toLowerCase()),el=Za(e=>e.charAt(0).toUpperCase()+e.slice(1)),Vl=Za(e=>e?`on${el(e)}`:""),Ln=(e,t)=>!Object.is(e,t),ia=(e,...t)=>{for(let n=0;n<e.length;n++)e[n](...t)},Yp=(e,t,n,r=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},Sa=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let hd;const Kp=()=>hd||(hd=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function sn(e){if(de(e)){const t={};for(let n=0;n<e.length;n++){const r=e[n],s=pt(r)?Cy(r):sn(r);if(s)for(const o in s)t[o]=s[o]}return t}else if(pt(e)||qe(e))return e}const Ay=/;(?![^(]*\))/g,Ty=/:([^]+)/,Sy=/\/\*[^]*?\*\//g;function Cy(e){const t={};return e.replace(Sy,"").split(Ay).forEach(n=>{if(n){const r=n.split(Ty);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function It(e){let t="";if(pt(e))t=e;else if(de(e))for(let n=0;n<e.length;n++){const r=It(e[n]);r&&(t+=r+" ")}else if(qe(e))for(const n in e)e[n]&&(t+=n+" ");return t.trim()}const Oy="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",xy=ju(Oy);function qp(e){return!!e||e===""}function Ny(e,t){if(e.length!==t.length)return!1;let n=!0;for(let r=0;n&&r<e.length;r++)n=di(e[r],t[r]);return n}function di(e,t){if(e===t)return!0;let n=dd(e),r=dd(t);if(n||r)return n&&r?e.getTime()===t.getTime():!1;if(n=Xn(e),r=Xn(t),n||r)return e===t;if(n=de(e),r=de(t),n||r)return n&&r?Ny(e,t):!1;if(n=qe(e),r=qe(t),n||r){if(!n||!r)return!1;const s=Object.keys(e).length,o=Object.keys(t).length;if(s!==o)return!1;for(const i in e){const a=e.hasOwnProperty(i),l=t.hasOwnProperty(i);if(a&&!l||!a&&l||!di(e[i],t[i]))return!1}}return String(e)===String(t)}function Yu(e,t){return e.findIndex(n=>di(n,t))}const j=e=>pt(e)?e:e==null?"":de(e)||qe(e)&&(e.toString===Wp||!Ae(e.toString))?JSON.stringify(e,Gp,2):String(e),Gp=(e,t)=>t&&t.__v_isRef?Gp(e,t.value):Vs(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],o)=>(n[Ul(r,o)+" =>"]=s,n),{})}:lo(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Ul(n))}:Xn(t)?Ul(t):qe(t)&&!de(t)&&!zp(t)?String(t):t,Ul=(e,t="")=>{var n;return Xn(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/**
* @vue/reactivity v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/let zt;class Xp{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=zt,!t&&zt&&(this.index=(zt.scopes||(zt.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=zt;try{return zt=this,t()}finally{zt=n}}}on(){zt=this}off(){zt=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n<r;n++)this.effects[n].stop();for(n=0,r=this.cleanups.length;n<r;n++)this.cleanups[n]();if(this.scopes)for(n=0,r=this.scopes.length;n<r;n++)this.scopes[n].stop(!0);if(!this.detached&&this.parent&&!t){const s=this.parent.scopes.pop();s&&s!==this&&(this.parent.scopes[this.index]=s,s.index=this.index)}this.parent=void 0,this._active=!1}}}function Ku(e){return new Xp(e)}function ky(e,t=zt){t&&t.active&&t.effects.push(e)}function Qp(){return zt}function Iy(e){zt&&zt.cleanups.push(e)}let is;class qu{constructor(t,n,r,s){this.fn=t,this.trigger=n,this.scheduler=r,this.active=!0,this.deps=[],this._dirtyLevel=5,this._trackId=0,this._runnings=0,this._shouldSchedule=!1,this._depsLength=0,ky(this,s)}get dirty(){if(this._dirtyLevel===2)return!1;if(this._dirtyLevel===3||this._dirtyLevel===4){this._dirtyLevel=1,Ur();for(let t=0;t<this._depsLength;t++){const n=this.deps[t];if(n.computed){if(n.computed.effect._dirtyLevel===2)return!0;if($y(n.computed),this._dirtyLevel>=5)break}}this._dirtyLevel===1&&(this._dirtyLevel=0),Hr()}return this._dirtyLevel>=5}set dirty(t){this._dirtyLevel=t?5:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Or,n=is;try{return Or=!0,is=this,this._runnings++,md(this),this.fn()}finally{pd(this),this._runnings--,is=n,Or=t}}stop(){this.active&&(md(this),pd(this),this.onStop&&this.onStop(),this.active=!1)}}function $y(e){return e.value}function md(e){e._trackId++,e._depsLength=0}function pd(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t<e.deps.length;t++)Jp(e.deps[t],e);e.deps.length=e._depsLength}}function Jp(e,t){const n=e.get(t);n!==void 0&&t._trackId!==n&&(e.delete(t),e.size===0&&e.cleanup())}let Or=!0,Pc=0;const Zp=[];function Ur(){Zp.push(Or),Or=!1}function Hr(){const e=Zp.pop();Or=e===void 0?!0:e}function Gu(){Pc++}function Xu(){for(Pc--;!Pc&&Rc.length;)Rc.shift()()}function eg(e,t,n){if(t.get(e)!==e._trackId){t.set(e,e._trackId);const r=e.deps[e._depsLength];r!==t?(r&&Jp(r,e),e.deps[e._depsLength++]=t):e._depsLength++}}const Rc=[];function tg(e,t,n){Gu();for(const r of e.keys()){if(!e.computed&&r.computed&&e.get(r)===r._trackId&&r._runnings>0){r._dirtyLevel=2;continue}let s;r._dirtyLevel<t&&(s??(s=e.get(r)===r._trackId))&&(r._shouldSchedule||(r._shouldSchedule=r._dirtyLevel===0),r.computed&&r._dirtyLevel===2&&(r._shouldSchedule=!0),r._dirtyLevel=t),r._shouldSchedule&&(s??(s=e.get(r)===r._trackId))&&(r.trigger(),(!r._runnings||r.allowRecurse)&&r._dirtyLevel!==3&&(r._shouldSchedule=!1,r.scheduler&&Rc.push(r.scheduler)))}Xu()}const ng=(e,t)=>{const n=new Map;return n.cleanup=e,n.computed=t,n},Ca=new WeakMap,as=Symbol(""),Dc=Symbol("");function Ut(e,t,n){if(Or&&is){let r=Ca.get(e);r||Ca.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=ng(()=>r.delete(n))),eg(is,s)}}function zn(e,t,n,r,s,o){const i=Ca.get(e);if(!i)return;let a=[];if(t==="clear")a=[...i.values()];else if(n==="length"&&de(e)){const l=Number(r);i.forEach((u,c)=>{(c==="length"||!Xn(c)&&c>=l)&&a.push(u)})}else switch(n!==void 0&&a.push(i.get(n)),t){case"add":de(e)?zu(n)&&a.push(i.get("length")):(a.push(i.get(as)),Vs(e)&&a.push(i.get(Dc)));break;case"delete":de(e)||(a.push(i.get(as)),Vs(e)&&a.push(i.get(Dc)));break;case"set":Vs(e)&&a.push(i.get(as));break}Gu();for(const l of a)l&&tg(l,5);Xu()}function Ly(e,t){const n=Ca.get(e);return n&&n.get(t)}const Py=ju("__proto__,__v_isRef,__isVue"),rg=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Xn)),gd=Ry();function Ry(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=De(this);for(let o=0,i=this.length;o<i;o++)Ut(r,"get",o+"");const s=r[t](...n);return s===-1||s===!1?r[t](...n.map(De)):s}}),["push","pop","shift","unshift","splice"].forEach(t=>{e[t]=function(...n){Ur(),Gu();const r=De(this)[t].apply(this,n);return Xu(),Hr(),r}}),e}function Dy(e){Xn(e)||(e=String(e));const t=De(this);return Ut(t,"has",e),t.hasOwnProperty(e)}class sg{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){const s=this._isReadonly,o=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw")return r===(s?o?Gy:lg:o?ag:ig).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const i=de(t);if(!s){if(i&&Pe(gd,n))return Reflect.get(gd,n,r);if(n==="hasOwnProperty")return Dy}const a=Reflect.get(t,n,r);return(Xn(n)?rg.has(n):Py(n))||(s||Ut(t,"get",n),o)?a:Ke(a)?i&&zu(n)?a:a.value:qe(a)?s?ug(a):rr(a):a}}class og extends sg{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];if(!this._isShallow){const l=Ys(o);if(!Oa(rLine truncated
* @vue/runtime-core v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/function Nr(e,t,n,r){try{return r?e(...r):e()}catch(s){nl(s,t,n)}}function bn(e,t,n,r){if(Ae(e)){const s=Nr(e,t,n,r);return s&&Bp(s)&&s.catch(o=>{nl(o,t,n)}),s}if(de(e)){const s=[];for(let o=0;o<e.length;o++)s.push(bn(e[o],t,n,r));return s}}function nl(e,t,n,r=!0){const s=t?t.vnode:null;if(t){let o=t.parent;const i=t.proxy,a=`https://vuejs.org/error-reference/#runtime-${n}`;for(;o;){const u=o.ec;if(u){for(let c=0;c<u.length;c++)if(u[c](e,i,a)===!1)return}o=o.parent}const l=t.appContext.config.errorHandler;if(l){Ur(),Nr(l,null,10,[e,i,a]),Hr();return}}o1(e,n,s,r)}function o1(e,t,n,r=!0){console.error(e)}let Xo=!1,Mc=!1;const St=[];let On=0;const Us=[];let gr=null,es=0;const gg=Promise.resolve();let sf=null;function kr(e){const t=sf||gg;return e?t.then(this?e.bind(this):e):t}function i1(e){let t=On+1,n=St.length;for(;t<n;){const r=t+n>>>1,s=St[r],o=Qo(s);o<e||o===e&&s.pre?t=r+1:n=r}return t}function of(e){(!St.length||!St.includes(e,Xo&&e.allowRecurse?On+1:On))&&(e.id==null?St.push(e):St.splice(i1(e.id),0,e),_g())}function _g(){!Xo&&!Mc&&(Mc=!0,sf=gg.then(bg))}function a1(e){const t=St.indexOf(e);t>On&&St.splice(t,1)}function l1(e){de(e)?Us.push(...e):(!gr||!gr.includes(e,e.allowRecurse?es+1:es))&&Us.push(e),_g()}function Ed(e,t,n=Xo?On+1:0){for(;n<St.length;n++){const r=St[n];if(r&&r.pre){if(e&&r.id!==e.uid)continue;St.splice(n,1),n--,r()}}}function vg(e){if(Us.length){const t=[...new Set(Us)].sort((n,r)=>Qo(n)-Qo(r));if(Us.length=0,gr){gr.push(...t);return}for(gr=t,es=0;es<gr.length;es++){const n=gr[es];n.active!==!1&&n()}gr=null,es=0}}const Qo=e=>e.id==null?1/0:e.id,c1=(e,t)=>{const n=Qo(e)-Qo(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function bg(e){Mc=!1,Xo=!0,St.sort(c1);try{for(On=0;On<St.length;On++){const t=St[On];t&&t.active!==!1&&Nr(t,null,14)}}finally{On=0,St.length=0,vg(),Xo=!1,sf=null,(St.length||Us.length)&&bg()}}function u1(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||ze;let s=n;const o=t.startsWith("update:"),i=o&&t.slice(7);if(i&&i in r){const c=`${i==="modelValue"?"model":i}Modifiers`,{number:f,trim:d}=r[c]||ze;d&&(s=n.map(h=>pt(h)?h.trim():h)),f&&(s=n.map(Sa))}let a,l=r[a=Vl(t)]||r[a=Vl(yn(t))];!l&&o&&(l=r[a=Vl(Vr(t))]),l&&bn(l,e,6,s);const u=r[a+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,bn(u,e,6,s)}}function yg(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let i={},a=!1;if(!Ae(e)){const l=u=>{const c=yg(u,t,!0);c&&(a=!0,mt(i,c))};!n&&t.mixins.length&&t.mixins.forEach(l),e.extends&&l(e.extends),e.mixins&&e.mixins.forEach(l)}return!o&&!a?(qe(e)&&r.set(e,null),null):(de(o)?o.forEach(l=>i[l]=null):mt(i,o),qe(e)&&r.set(e,i),i)}function rl(e,t){return!e||!Ja(t)?!1:(t=t.slice(2).replace(/Once$/,""),Pe(e,t[0].toLowerCase()+t.slice(1))||Pe(e,Vr(t))||Pe(e,t))}let kt=null,sl=null;function xa(e){const t=kt;return kt=e,sl=e&&e.type.__scopeId||null,t}function ol(e){sl=e}function il(){sl=null}function mn(e,t=kt,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&$d(-1);const o=xa(t);let i;try{i=e(...s)}finally{xa(o),r._d&&$d(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Hl(e){const{type:t,vnode:n,proxy:r,withProxy:s,propsOptions:[o],slots:i,attrs:a,emit:l,render:u,renderCache:c,props:f,data:d,setupState:h,ctx:m,inheritAttrs:g}=e,v=xa(e);let y,S;try{if(n.shapeFlag&4){const A=s||r,x=A;y=Cn(u.call(x,A,c,f,h,d,m)),S=a}else{const A=t;y=Cn(A.length>1?A(f,{attrs:a,slots:i,emit:l}):A(f,null)),S=t.props?a:f1(a)}}catch(A){Do.length=0,nl(A,e,1),y=re(fs)}let E=y;if(S&&g!==!1){const A=Object.keys(S),{shapeFlag:x}=E;A.length&&x&7&&(o&&A.some(Bu)&&(S=d1(S,o)),E=Ks(E,S,!1,!0))}return n.dirs&&(E=Ks(E,null,!1,!0),E.dirs=E.dirs?E.dirs.concat(n.dirs):n.dirs),n.transition&&(E.transition=n.transition),y=E,xa(v),y}const f1=e=>{let t;for(const n in e)(n==="class"||n==="style"||Ja(n))&&((t||(t={}))[n]=e[n]);return t},d1=(e,t)=>{const n={};for(const r in e)(!Bu(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function h1(e,t,n){const{props:r,children:s,component:o}=e,{props:i,children:a,patchFlag:l}=t,u=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&l>=0){if(l&1024)return!0;if(l&16)return r?wd(r,i,u):!!i;if(l&8){const c=t.dynamicProps;for(let f=0;f<c.length;f++){const d=c[f];if(i[d]!==r[d]&&!rl(u,d))return!0}}}else return(s||a)&&(!a||!a.$stable)?!0:r===i?!1:r?i?wd(r,i,u):!0:!!i;return!1}function wd(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let s=0;s<r.length;s++){const o=r[s];if(t[o]!==e[o]&&!rl(n,o))return!0}return!1}function m1({vnode:e,parent:t},n){for(;t;){const r=t.subTree;if(r.suspense&&r.suspense.activeBranch===e&&(r.el=e.el),r===e)(e=t.vnode).el=n,t=t.parent;else break}}const p1="components";function af(e,t){return _1(p1,e,!0,t)||e}const g1=Symbol.for("v-ndc");function _1(e,t,n=!0,r=!1){const s=kt||_t;if(s){const o=s.type;{const a=u0(o,!1);if(a&&(a===t||a===yn(t)||a===el(yn(t))))return o}const i=Ad(s[e]||o[e],t)||Ad(s.appContext[e],t);return!i&&r?o:i}}f Line truncated
* @vue/runtime-dom v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/const h0="http://www.w3.org/2000/svg",m0="http://www.w3.org/1998/Math/MathML",Hn=typeof document<"u"?document:null,Dd=Hn&&Hn.createElement("template"),p0={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?Hn.createElementNS(h0,e):t==="mathml"?Hn.createElementNS(m0,e):n?Hn.createElement(e,{is:n}):Hn.createElement(e);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>Hn.createTextNode(e),createComment:e=>Hn.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Hn.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const i=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{Dd.innerHTML=r==="svg"?`<svg>${e}</svg>`:r==="mathml"?`<math>${e}</math>`:e;const a=Dd.content;if(r==="svg"||r==="mathml"){const l=a.firstChild;for(;l.firstChild;)a.appendChild(l.firstChild);a.removeChild(l)}t.insertBefore(a,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},g0=Symbol("_vtc");function _0(e,t,n){const r=e[g0];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Md=Symbol("_vod"),v0=Symbol("_vsh"),b0=Symbol(""),y0=/(^|;)\s*display\s*:/;function E0(e,t,n){const r=e.style,s=pt(n);let o=!1;if(n&&!s){if(t)if(pt(t))for(const i of t.split(";")){const a=i.slice(0,i.indexOf(":")).trim();n[a]==null&&ua(r,a,"")}else for(const i in t)n[i]==null&&ua(r,i,"");for(const i in n)i==="display"&&(o=!0),ua(r,i,n[i])}else if(s){if(t!==n){const i=r[b0];i&&(n+=";"+i),r.cssText=n,o=y0.test(n)}}else t&&e.removeAttribute("style");Md in e&&(e[Md]=o?r.display:"",e[v0]&&(r.display="none"))}const Fd=/\s*!important$/;function ua(e,t,n){if(de(n))n.forEach(r=>ua(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=w0(e,t);Fd.test(n)?e.setProperty(Vr(r),n.replace(Fd,""),"important"):e[r]=n}}const Vd=["Webkit","Moz","ms"],Wl={};function w0(e,t){const n=Wl[t];if(n)return n;let r=yn(t);if(r!=="filter"&&r in e)return Wl[t]=r;r=el(r);for(let s=0;s<Vd.length;s++){const o=Vd[s]+r;if(o in e)return Wl[t]=o}return t}const Ud="http://www.w3.org/1999/xlink";function Hd(e,t,n,r,s,o=xy(t)){r&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(Ud,t.slice(6,t.length)):e.setAttributeNS(Ud,t,n):n==null||o&&!qp(n)?e.removeAttribute(t):e.setAttribute(t,o?"":String(n))}function A0(e,t,n,r,s,o,i){if(t==="innerHTML"||t==="textContent"){r&&i(r,s,o),e[t]=n??"";return}const a=e.tagName;if(t==="value"&&a!=="PROGRESS"&&!a.includes("-")){const u=a==="OPTION"?e.getAttribute("value")||"":e.value,c=n==null?"":String(n);(u!==c||!("_value"in e))&&(e.value=c),n==null&&e.removeAttribute(t),e._value=n;return}let l=!1;if(n===""||n==null){const u=typeof e[t];u==="boolean"?n=qp(n):n==null&&u==="string"?(n="",l=!0):u==="number"&&(n=0,l=!0)}try{e[t]=n}catch{}l&&e.removeAttribute(t)}function wr(e,t,n,r){e.addEventListener(t,n,r)}function T0(e,t,n,r){e.removeEventListener(t,n,r)}const jd=Symbol("_vei");function S0(e,t,n,r,s=null){const o=e[jd]||(e[jd]={}),i=o[t];if(r&&i)i.value=r;else{const[a,l]=C0(t);if(r){const u=o[t]=N0(r,s);wr(e,a,u,l)}else i&&(T0(e,a,i,l),o[t]=void 0)}}const Bd=/(?:Once|Passive|Capture)$/;function C0(e){let t;if(Bd.test(e)){t={};let r;for(;r=e.match(Bd);)e=e.slice(0,e.length-r[0].length),t[r[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):Vr(e.slice(2)),t]}let zl=0;const O0=Promise.resolve(),x0=()=>zl||(O0.then(()=>zl=0),zl=Date.now());function N0(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;bn(k0(r,n.value),t,5,[r])};return n.value=e,n.attached=x0(),n}function k0(e,t){if(de(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const Wd=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,I0=(e,t,n,r,s,o,i,a,l)=>{const u=s==="svg";t==="class"?_0(e,r,u):t==="style"?E0(e,n,r):Ja(t)?Bu(t)||S0(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):$0(e,t,r,u))?(A0(e,t,r,o,i,a,l),(t==="value"||t==="checked"||t==="selected")&&Hd(e,t,r,u,i,t!=="value")):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Hd(e,t,r,u))};function $0(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&Wd(t)&&Ae(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return Wd(t)&&pt(n)?!1:t in e}const qs=e=>{const t=e.props["onUpdate:modelValue"]||!1;return de(t)?n=>ia(t,n):t};function L0(e){e.target.composing=!0}fun Line truncated
* pinia v2.1.7
* (c) 2023 Eduardo San Martin Morote
* @license MIT
*/let Bg;const ul=e=>Bg=e,Wg=Symbol();function Yc(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var Mo;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(Mo||(Mo={}));function j0(){const e=Ku(!0),t=e.run(()=>te({}));let n=[],r=[];const s=ef({install(o){ul(s),s._a=o,o.provide(Wg,s),o.config.globalProperties.$pinia=s,r.forEach(i=>n.push(i)),r=[]},use(o){return!this._a&&!H0?r.push(o):n.push(o),this},_p:n,_a:null,_e:e,_s:new Map,state:t});return s}const zg=()=>{};function Gd(e,t,n,r=zg){e.push(t);const s=()=>{const o=e.indexOf(t);o>-1&&(e.splice(o,1),r())};return!n&&Qp()&&Iy(s),s}function Es(e,...t){e.slice().forEach(n=>{n(...t)})}const B0=e=>e();function Kc(e,t){e instanceof Map&&t instanceof Map&&t.forEach((n,r)=>e.set(r,n)),e instanceof Set&&t instanceof Set&&t.forEach(e.add,e);for(const n in t){if(!t.hasOwnProperty(n))continue;const r=t[n],s=e[n];Yc(s)&&Yc(r)&&e.hasOwnProperty(n)&&!Ke(r)&&!xr(r)?e[n]=Kc(s,r):e[n]=r}return e}const W0=Symbol();function z0(e){return!Yc(e)||!e.hasOwnProperty(W0)}const{assign:pr}=Object;function Y0(e){return!!(Ke(e)&&e.effect)}function K0(e,t,n,r){const{state:s,actions:o,getters:i}=t,a=n.state.value[e];let l;function u(){a||(n.state.value[e]=s?s():{});const c=pg(n.state.value[e]);return pr(c,o,Object.keys(i||{}).reduce((f,d)=>(f[d]=ef(oe(()=>{ul(n);const h=n._s.get(e);return i[d].call(h,h)})),f),{}))}return l=Yg(e,u,t,n,r,!0),l}function Yg(e,t,n={},r,s,o){let i;const a=pr({actions:{}},n),l={deep:!0};let u,c,f=[],d=[],h;const m=r.state.value[e];!o&&!m&&(r.state.value[e]={}),te({});let g;function v(P){let $;u=c=!1,typeof P=="function"?(P(r.state.value[e]),$={type:Mo.patchFunction,storeId:e,events:h}):(Kc(r.state.value[e],P),$={type:Mo.patchObject,payload:P,storeId:e,events:h});const V=g=Symbol();kr().then(()=>{g===V&&(u=!0)}),c=!0,Es(f,$,r.state.value[e])}const y=o?function(){const{state:$}=n,V=$?$():{};this.$patch(Y=>{pr(Y,V)})}:zg;function S(){i.stop(),f=[],d=[],r._s.delete(e)}function E(P,$){return function(){ul(r);const V=Array.from(arguments),Y=[],q=[];function le(ie){Y.push(ie)}function Ie(ie){q.push(ie)}Es(d,{args:V,name:P,store:x,after:le,onError:Ie});let Ce;try{Ce=$.apply(this&&this.$id===e?this:x,V)}catch(ie){throw Es(q,ie),ie}return Ce instanceof Promise?Ce.then(ie=>(Es(Y,ie),ie)).catch(ie=>(Es(q,ie),Promise.reject(ie))):(Es(Y,Ce),Ce)}}const A={_p:r,$id:e,$onAction:Gd.bind(null,d),$patch:v,$reset:y,$subscribe(P,$={}){const V=Gd(f,P,$.detached,()=>Y()),Y=i.run(()=>Et(()=>r.state.value[e],q=>{($.flush==="sync"?c:u)&&P({storeId:e,type:Mo.direct,events:h},q)},pr({},l,$)));return V},$dispose:S},x=rr(A);r._s.set(e,x);const k=(r._a&&r._a.runWithContext||B0)(()=>r._e.run(()=>(i=Ku()).run(t)));for(const P in k){const $=k[P];if(Ke($)&&!Y0($)||xr($))o||(m&&z0($)&&(Ke($)?$.value=m[P]:Kc($,m[P])),r.state.value[e][P]=$);else if(typeof $=="function"){const V=E(P,$);k[P]=V,a.actions[P]=$}}return pr(x,k),pr(De(x),k),Object.defineProperty(x,"$state",{get:()=>r.state.value[e],set:P=>{v($=>{pr($,P)})}}),r._p.forEach(P=>{pr(x,i.run(()=>P({store:x,app:r._a,pinia:r,options:a})))}),m&&o&&n.hydrate&&n.hydrate(x.$state,m),u=!0,c=!0,x}function Kg(e,t,n){let r,s;const o=typeof t=="function";typeof e=="string"?(r=e,s=o?n:t):(s=e,r=e.id);function i(a,l){const u=P1();return a=a||(u?tt(Wg,null):null),a&&ul(a),a=Bg,a._s.has(r)||(o?Yg(r,t,s,a):K0(r,s,a)),a._s.get(r)}return i.$id=r,i}/*!
* shared v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/const $a=typeof window<"u",jr=(e,t=!1)=>t?Symbol.for(e):Symbol(e),q0=(e,t,n)=>G0({l:e,k:t,s:n}),G0=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),ft=e=>typeof e=="number"&&isFinite(e),X0=e=>Gg(e)==="[object Date]",Ir=e=>Gg(e)==="[object RegExp]",fl=e=>be(e)&&Object.keys(e).length===0,wt=Object.assign;let Xd;const jn=()=>Xd||(Xd=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Qd(e){return e.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}const Q0=Object.prototype.hasOwnProperty;function La(e,t){return Q0.call(e,t)}const Xe=Array.isArray,Ye=e=>typeof e=="function",ne=e=>typeof e=="string",Oe=e=>typeof e=="boolean",Ue=e=>e!==null&&typeof e=="object",J0=e=>Ue(e)&&Ye(e.then)&&Ye(e.catch),qg=Object.prototype.toString,Gg=e=>qg.call(e),be=e=>{if(!Ue(e))return!1;const t=Object.getPrototypeOf(e);return t===null||t.constructor===Object},Z0=e=>e==null?"":Xe(e)||be(e)&&e.toString===qg?JSON.stringify(e,null,2):String(e);function eE(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}function dl(e){let t=e;return()=>++t}function tE(e,t){typeof console<"u"&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const Mi=e=>!Ue(e)||Xe(e);function fa(e,t){if(Mi(e)||Mi(t))throw new Error("Invalid value");const n=[{src:e,des:t}];for(;n.length;){const{src:r,des:s}=n.pop();Object.keys(r).forEach(o=>{Mi(r[o])||Mi(s[o])?s[o]=r[o]:n.push({src:r[o],des:s[o]})})}}/*!
* message-compiler v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/function nE(e,t,n){return{line:e,column:t,offset:n}}function Pa(e,t,n){return{start:e,end:t}}const rE=/\{([0-9a-zA-Z]+)\}/g;function Xg(e,...t){return t.length===1&&sE(t[0])&&(t=t[0]),(!t||!t.hasOwnProperty)&&(t={}),e.replace(rE,(n,r)=>t.hasOwnProperty(r)?t[r]:"")}const Qg=Object.assign,Jd=e=>typeof e=="string",sE=e=>e!==null&&typeof e=="object";function Jg(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}const hf={USE_MODULO_SYNTAX:1,__EXTEND_POINT__:2},oE={[hf.USE_MODULO_SYNTAX]:"Use modulo before '{{0}}'."};function iE(e,t,...n){const r=Xg(oE[e],...n||[]),s={message:String(r),code:e};return t&&(s.location=t),s}const pe={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16,__EXTEND_POINT__:17},aE={[pe.EXPECTED_TOKEN]:"Expected token: '{0}'",[pe.INVALID_TOKEN_IN_PLACEHOLDER]:"Invalid token in placeholder: '{0}'",[pe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]:"Unterminated single quote in placeholder",[pe.UNKNOWN_ESCAPE_SEQUENCE]:"Unknown escape sequence: \\{0}",[pe.INVALID_UNICODE_ESCAPE_SEQUENCE]:"Invalid unicode escape sequence: {0}",[pe.UNBALANCED_CLOSING_BRACE]:"Unbalanced closing brace",[pe.UNTERMINATED_CLOSING_BRACE]:"Unterminated closing brace",[pe.EMPTY_PLACEHOLDER]:"Empty placeholder",[pe.NOT_ALLOW_NEST_PLACEHOLDER]:"Not allowed nest placeholder",[pe.INVALID_LINKED_FORMAT]:"Invalid linked format",[pe.MUST_HAVE_MESSAGES_IN_PLURAL]:"Plural must have messages",[pe.UNEXPECTED_EMPTY_LINKED_MODIFIER]:"Unexpected empty linked modifier",[pe.UNEXPECTED_EMPTY_LINKED_KEY]:"Unexpected empty linked key",[pe.UNEXPECTED_LEXICAL_ANALYSIS]:"Unexpected lexical analysis in token: '{0}'",[pe.UNHANDLED_CODEGEN_NODE_TYPE]:"unhandled codegen node type: '{0}'",[pe.UNHANDLED_MINIFIER_NODE_TYPE]:"unhandled mimifier node type: '{0}'"};function fo(e,t,n={}){const{domain:r,messages:s,args:o}=n,i=Xg((s||aE)[e]||"",...o||[]),a=new SyntaxError(String(i));return a.code=e,t&&(a.location=t),a.domain=r,a}function lE(e){throw e}const Fn=" ",cE="\r",xt=`
`,uE="\u2028",fE="\u2029";function dE(e){const t=e;let n=0,r=1,s=1,o=0;const i=k=>t[k]===cE&&t[k+1]===xt,a=k=>t[k]===xt,l=k=>t[k]===fE,u=k=>t[k]===uE,c=k=>i(k)||a(k)||l(k)||u(k),f=()=>n,d=()=>r,h=()=>s,m=()=>o,g=k=>i(k)||l(k)||u(k)?xt:t[k],v=()=>g(n),y=()=>g(n+o);function S(){return o=0,c(n)&&(r++,s=0),i(n)&&n++,n++,s++,t[n]}function E(){return i(n+o)&&o++,o++,t[n+o]}function A(){n=0,r=1,s=1,o=0}function x(k=0){o=k}function O(){const k=n+o;for(;k!==n;)S();o=0}return{index:f,line:d,column:h,peekOffset:m,charAt:g,currentChar:v,currentPeek:y,next:S,peek:E,reset:A,resetPeek:x,skipToPeek:O}}const ur=void 0,hE=".",Zd="'",mE="tokenizer";function pE(e,t={}){const n=t.location!==!1,r=dE(e),s=()=>r.index(),o=()=>nE(r.line(),r.column(),r.index()),i=o(),a=s(),l={currentType:14,offset:a,startLoc:i,endLoc:i,lastType:14,lastOffset:a,lastStartLoc:i,lastEndLoc:i,braceNest:0,inLinked:!1,text:""},u=()=>l,{onError:c}=t;function f(_,w,N,...F){const Z=u();if(w.column+=N,w.offset+=N,c){const W=n?Pa(Z.startLoc,w):null,L=fo(_,W,{domain:mE,args:F});c(L)}}function d(_,w,N){_.endLoc=o(),_.currentType=w;const F={type:w};return n&&(F.loc=Pa(_.startLoc,_.endLoc)),N!=null&&(F.value=N),F}const h=_=>d(_,14);function m(_,w){return _.currentChar()===w?(_.next(),w):(f(pe.EXPECTED_TOKEN,o(),0,w),"")}function g(_){let w="";for(;_.currentPeek()===Fn||_.currentPeek()===xt;)w+=_.currentPeek(),_.peek();return w}function v(_){const w=g(_);return _.skipToPeek(),w}function y(_){if(_===ur)return!1;const w=_.charCodeAt(0);return w>=97&&w<=122||w>=65&&w<=90||w===95}function S(_){if(_===ur)return!1;const w=_.charCodeAt(0);return w>=48&&w<=57}function E(_,w){const{currentType:N}=w;if(N!==2)return!1;g(_);const F=y(_.currentPeek());return _.resetPeek(),F}function A(_,w){const{currentType:N}=w;if(N!==2)return!1;g(_);const F=_.currentPeek()==="-"?_.peek():_.currentPeek(),Z=S(F);return _.resetPeek(),Z}function x(_,w){const{currentType:N}=w;if(N!==2)return!1;g(_);const F=_.currentPeek()===Zd;return _.resetPeek(),F}function O(_,w){const{currentType:N}=w;if(N!==8)return!1;g(_);const F=_.currentPeek()===".";return _.resetPeek(),F}function k(_,w){const{currentType:N}=w;if(N!==9)return!1;g(_);const F=y(_.currentPeek());return _.resetPeek(),F}function P(_,w){const{currentType:N}=w;if(!(N===8||N===12))return!1;g(_);const F=_.currentPeek()===":";return _.resetPeek(),F}function $(_,w){const{currentType:N}=w;if(N!==10)return!1;const F=()=>{const W=_.currentPeek();return W==="{"?y(_.peek()):W==="@"||W==="%"||W==="|"||W===":"||W==="."||W===Fn||!W?!1:W===xt?(_.peek(),F()):q(_,!1)},Z=F();return _.resetPeek(),Z}function V(_){g(_);const w=_.currentPeek()==="|";return _.resetPeek(),w}function Y(_){const w=g(_),N=_.currentPeek()==="%"&&_.peek()==="{";return _.resetPeek(),{isModulo:N,hasSpace:w.length>0}}function q(_,w=!0){const N=(Z=!1,W="",L=!1)=>{const R=_.currentPeek();return R==="{"?W==="%"?!1:Z:R==="@"||!R?W==="%"?!0:Z:R==="%"?(_.peek(),N(Z,"%",!0)):R==="|"?W==="%"||L?!0:!(W===Fn||W===xt):R===Fn?(_.peek(),N(!0,Fn,L)):R===xt?(_.peek(),N(!0,xt,L)):!0},F=N();return w&&_.resetPeek(),F}function le(_,w){const N=_.currentChar();return N===ur?ur:w(N)?(_.next(),N):null}function Ie(_){const w=_.charCodeAt(0);return w>=97&&w<=122||w>=65&&w<=90||w>=48&&w<=57||w===95||w===36}function Ce(_){return le(_,Ie)}function ie(_){const w=_.charCodeAt(0);return w>=97&&w<=122||w>=65&&w<=90||w>=48&&w<=57||w===95||w===36||w===45}function fe(_){return le(_,ie)}function ve(_){const w=_.charCodeAt(0);return w>=48&&w<=57}function je(_){return le(_,ve)}function Ee(_){const w=_.charCodeAt(0);return w>=48&&w<=57||w>=65&&w<=70||w>=97&&w<=102}function $e(_){return le(_,Ee)}function xe(_){let w="",N="";for(;w=je(_);)N+=w;return N}function bt(_){v(_);const w=_.currentChar();return w!=="%"&&f(pe.EXPECTED_TOKEN,o(),0,w),_.next(),"%"}function at(_){let w="";for(;;){const N=_.currentChar();if(N==="{"||N==="}"||N==="@"||N==="|"||!N)break;if(N==="%")if(q(_))w+=N,_.next();else break;else if(N===Fn||N===xt)if(q(_))w+=N,_.next();else{if(V(_))break;w+=N,_.next()}else w+=N,_.next()}return w}function ut(_){v(_);let w="",N="";for(;w=fe(_);)N+=w;return _.currentChar()===ur&&f(pe.UNTERMINATED_CLOSING_BRACE,o(),0),N}function Be(_){v(_);let w="";return _.currentChar()==="-"?(_.next(),w+=`-${xe(_)}`):w+=xe(_),_.currentChar()===ur&&f(pe.UNTERMINATED_CLOSING_BRACE,o(),0),w}function U(_){return _!==Zd&&_!==xt}function J(_){v(_),m(_,"'");let w="",N="";for(;w=le(_,U);)w==="\\"?N+=X(_):N+=w;const F=_.currentChar();return F===xt||F===ur?(f(pe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,o(),0),F===xt&&(_.next(),m(_,"'")),N):(m(_,"'"),N)}function X(_){const w=_.currentChar();switch(w){case"\\":case"'":return _.next(),`\\${w}`;case"u":return ae(_,w,4);case"U":return ae(_,w,6);default:return f(pe.UNKNOWN_ESCAPE_SEQUENCE,o(),0,w),""}}function ae(_,w,N){m(_,w);let F="";for(let Z=0;Z<N;Z++){const W=$e(_);if(!W){f(pe.INVALID_UNICODE_ESCAPE_SEQUENCE,o(),0,`\\${w}${F}${_.currentChar()}`);break}F+=W}return`\\${w}${F}`}function Te(_){return _!=="{"&&_ Line truncated
`,i=t.needIndent?t.needIndent:n!=="arrow",a=e.helpers||[],l=SE(e,{mode:n,filename:r,sourceMap:s,breakLineCode:o,needIndent:i});l.push(n==="normal"?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(i),a.length>0&&(l.push(`const { ${Jg(a.map(f=>`${f}: _${f}`),", ")} } = ctx`),l.newline()),l.push("return "),Gs(l,e),l.deindent(i),l.push("}"),delete e.helpers;const{code:u,map:c}=l.context();return{ast:e,code:u,map:c?c.toJSON():void 0}};function IE(e,t={}){const n=Qg({},t),r=!!n.jit,s=!!n.minify,o=n.optimize==null?!0:n.optimize,a=bE(n).parse(e);return r?(o&&wE(a),s&&Cs(a),{ast:a,code:""}):(EE(a,n),kE(a,n))}/*!
* core-base v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/function $E(){typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(jn().__INTLIFY_PROD_DEVTOOLS__=!1),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(jn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(jn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}const Br=[];Br[0]={w:[0],i:[3,0],"[":[4],o:[7]};Br[1]={w:[1],".":[2],"[":[4],o:[7]};Br[2]={w:[2],i:[3,0],0:[3,0]};Br[3]={i:[3,0],0:[3,0],w:[1,1],".":[2,1],"[":[4,1],o:[7,1]};Br[4]={"'":[5,0],'"':[6,0],"[":[4,2],"]":[1,3],o:8,l:[4,0]};Br[5]={"'":[4,0],o:8,l:[5,0]};Br[6]={'"':[4,0],o:8,l:[6,0]};const LE=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function PE(e){return LE.test(e)}function RE(e){const t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t===n&&(t===34||t===39)?e.slice(1,-1):e}function DE(e){if(e==null)return"o";switch(e.charCodeAt(0)){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function ME(e){const t=e.trim();return e.charAt(0)==="0"&&isNaN(parseInt(e))?!1:PE(t)?RE(t):"*"+t}function FE(e){const t=[];let n=-1,r=0,s=0,o,i,a,l,u,c,f;const d=[];d[0]=()=>{i===void 0?i=a:i+=a},d[1]=()=>{i!==void 0&&(t.push(i),i=void 0)},d[2]=()=>{d[0](),s++},d[3]=()=>{if(s>0)s--,r=4,d[0]();else{if(s=0,i===void 0||(i=ME(i),i===!1))return!1;d[1]()}};function h(){const m=e[n+1];if(r===5&&m==="'"||r===6&&m==='"')return n++,a="\\"+m,d[0](),!0}for(;r!==null;)if(n++,o=e[n],!(o==="\\"&&h())){if(l=DE(o),f=Br[r],u=f[l]||f.l||8,u===8||(r=u[0],u[1]!==void 0&&(c=d[u[1]],c&&(a=o,c()===!1))))return;if(r===7)return t}}const nh=new Map;function VE(e,t){return Ue(e)?e[t]:null}function UE(e,t){if(!Ue(e))return null;let n=nh.get(t);if(n||(n=FE(t),n&&nh.set(t,n)),!n)return null;const r=n.length;let s=e,o=0;for(;o<r;){const i=s[n[o]];if(i===void 0||Ye(s))return null;s=i,o++}return s}const HE=e=>e,jE=e=>"",BE="text",WE=e=>e.length===0?"":eE(e),zE=Z0;function rh(e,t){return e=Math.abs(e),t===2?e?e>1?1:0:1:e?Math.min(e,2):0}function YE(e){const t=ft(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(ft(e.named.count)||ft(e.named.n))?ft(e.named.count)?e.named.count:ft(e.named.n)?e.named.n:t:t}function KE(e,t){t.count||(t.count=e),t.n||(t.n=e)}function qE(e={}){const t=e.locale,n=YE(e),r=Ue(e.pluralRules)&&ne(t)&&Ye(e.pluralRules[t])?e.pluralRules[t]:rh,s=Ue(e.pluralRules)&&ne(t)&&Ye(e.pluralRules[t])?rh:void 0,o=y=>y[r(n,y.length,s)],i=e.list||[],a=y=>i[y],l=e.named||{};ft(e.pluralIndex)&&KE(n,l);const u=y=>l[y];function c(y){const S=Ye(e.messages)?e.messages(y):Ue(e.messages)?e.messages[y]:!1;return S||(e.parent?e.parent.message(y):jE)}const f=y=>e.modifiers?e.modifiers[y]:HE,d=be(e.processor)&&Ye(e.processor.normalize)?e.processor.normalize:WE,h=be(e.processor)&&Ye(e.processor.interpolate)?e.processor.interpolate:zE,m=be(e.processor)&&ne(e.processor.type)?e.processor.type:BE,v={list:a,named:u,plural:o,linked:(y,...S)=>{const[E,A]=S;let x="text",O="";S.length===1?Ue(E)?(O=E.modifier||O,x=E.type||x):ne(E)&&(O=E||O):S.length===2&&(ne(E)&&(O=E||O),ne(A)&&(x=A||x));const k=c(y)(v),P=x==="vnode"&&Xe(k)&&O?k[0]:k;return O?f(O)(P,x):P},message:c,type:m,interpolate:h,normalize:d,values:wt({},i,l)};return v}let ei=null;function GE(e){ei=e}function XE(e,t,n){ei&&ei.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const QE=JE("function:translate");function JE(e){return t=>ei&&ei.emit(e,t)}const Zg=hf.__EXTEND_POINT__,Gr=dl(Zg),ZE={NOT_FOUND_KEY:Zg,FALLBACK_TO_TRANSLATE:Gr(),CANNOT_FORMAT_NUMBER:Gr(),FALLBACK_TO_NUMBER_FORMAT:Gr(),CANNOT_FORMAT_DATE:Gr(),FALLBACK_TO_DATE_FORMAT:Gr(),EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER:Gr(),__EXTEND_POINT__:Gr()},e_=pe.__EXTEND_POINT__,Xr=dl(e_),_n={INVALID_ARGUMENT:e_,INVALID_DATE_ARGUMENT:Xr(),INVALID_ISO_DATE_ARGUMENT:Xr(),NOT_SUPPORT_NON_STRING_MESSAGE:Xr(),NOT_SUPPORT_LOCALE_PROMISE_VALUE:Xr(),NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:Xr(),NOT_SUPPORT_LOCALE_TYPE:Xr(),__EXTEND_POINT__:Xr()};function xn(e){return fo(e,null,void 0)}function pf(e,t){return t.locale!=null?sh(t.locale):sh(e.locale)}let Yl;function sh(e){if(ne(e))return e;if(Ye(e)){if(e.resolvedOnce&&Yl!=null)return Yl;if(e.constructor.name==="Function"){const t=e();if(J0(t))throw xn(_n.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return Yl=t}else throw xn(_n.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}else throw xn(_n.NOT_SUPPORT_LOCALE_TYPE)}function ew(e,t,n){return[...new Set([n,...Xe(t)?t:Ue(t)?Object.keys(t):ne(t)?[t]:[n]])]}function t_(e,t,n){const r=ne(n)?n:Xs,s=e;s.__localeChainCache||(s.__localeChainCache=new Map);let o=s.__localeChainCache.get(r);if(!o){o=[];let i=[n];for(;Xe(i);)i=oh(o,i,t);const a=Xe(t)||!be(t)?t:t.default?t.default:null;i=ne(a)?[a]:a,Xe(i)&&oh(o,i,!1),s.__localeChainCache.set(r,o)}return o}function oh(e,t,n){let r=!0;for(let s=0;s<t.length&&Oe(r);s++){const o=t[s];ne(o)&&(r=tw(e,t[s],n))}return r}function tw(e,t,n){let r;const s=t.split("-");do{const o=s.join("-");r=nw(e,o,n),s.splice(-1,1)}while(s.length&&r===!0);return r}function nw(eLine truncated
* vue-i18n v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/const yw="9.13.1";function Ew(){typeof __VUE_I18N_FULL_INSTALL__!="boolean"&&(jn().__VUE_I18N_FULL_INSTALL__=!0),typeof __VUE_I18N_LEGACY_API__!="boolean"&&(jn().__VUE_I18N_LEGACY_API__=!0),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(jn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(jn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(jn().__INTLIFY_PROD_DEVTOOLS__=!1)}const h_=ZE.__EXTEND_POINT__,Vn=dl(h_);Vn(),Vn(),Vn(),Vn(),Vn(),Vn(),Vn(),Vn(),Vn();const m_=_n.__EXTEND_POINT__,Pt=dl(m_),ht={UNEXPECTED_RETURN_TYPE:m_,INVALID_ARGUMENT:Pt(),MUST_BE_CALL_SETUP_TOP:Pt(),NOT_INSTALLED:Pt(),NOT_AVAILABLE_IN_LEGACY_MODE:Pt(),REQUIRED_VALUE:Pt(),INVALID_VALUE:Pt(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:Pt(),NOT_INSTALLED_WITH_PROVIDE:Pt(),UNEXPECTED_ERROR:Pt(),NOT_COMPATIBLE_LEGACY_VUE_I18N:Pt(),BRIDGE_SUPPORT_VUE_2_ONLY:Pt(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:Pt(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:Pt(),__EXTEND_POINT__:Pt()};function vt(e,...t){return fo(e,null,void 0)}const Jc=jr("__translateVNode"),Zc=jr("__datetimeParts"),eu=jr("__numberParts"),p_=jr("__setPluralRules"),g_=jr("__injectWithOption"),tu=jr("__dispose");function ti(e){if(!Ue(e))return e;for(const t in e)if(La(e,t))if(!t.includes("."))Ue(e[t])&&ti(e[t]);else{const n=t.split("."),r=n.length-1;let s=e,o=!1;for(let i=0;i<r;i++){if(n[i]in s||(s[n[i]]={}),!Ue(s[n[i]])){o=!0;break}s=s[n[i]]}o||(s[n[r]]=e[t],delete e[t]),Ue(s[n[r]])&&ti(s[n[r]])}return e}function ml(e,t){const{messages:n,__i18n:r,messageResolver:s,flatJson:o}=t,i=be(n)?n:Xe(r)?{}:{[e]:{}};if(Xe(r)&&r.forEach(a=>{if("locale"in a&&"resource"in a){const{locale:l,resource:u}=a;l?(i[l]=i[l]||{},fa(u,i[l])):fa(u,i)}else ne(a)&&fa(JSON.parse(a),i)}),s==null&&o)for(const a in i)La(i,a)&&ti(i[a]);return i}function __(e){return e.type}function v_(e,t,n){let r=Ue(t.messages)?t.messages:{};"__i18nGlobal"in n&&(r=ml(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const s=Object.keys(r);s.length&&s.forEach(o=>{e.mergeLocaleMessage(o,r[o])});{if(Ue(t.datetimeFormats)){const o=Object.keys(t.datetimeFormats);o.length&&o.forEach(i=>{e.mergeDateTimeFormat(i,t.datetimeFormats[i])})}if(Ue(t.numberFormats)){const o=Object.keys(t.numberFormats);o.length&&o.forEach(i=>{e.mergeNumberFormat(i,t.numberFormats[i])})}}}function vh(e){return re(hi,null,e,0)}const bh="__INTLIFY_META__",yh=()=>[],ww=()=>!1;let Eh=0;function wh(e){return(t,n,r,s)=>e(n,r,Pn()||void 0,s)}const Aw=()=>{const e=Pn();let t=null;return e&&(t=__(e)[bh])?{[bh]:t}:null};function _f(e={},t){const{__root:n,__injectWithOption:r}=e,s=n===void 0,o=e.flatJson,i=$a?te:rf,a=!!e.translateExistCompatible;let l=Oe(e.inheritLocale)?e.inheritLocale:!0;const u=i(n&&l?n.locale.value:ne(e.locale)?e.locale:Xs),c=i(n&&l?n.fallbackLocale.value:ne(e.fallbackLocale)||Xe(e.fallbackLocale)||be(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:u.value),f=i(ml(u.value,e)),d=i(be(e.datetimeFormats)?e.datetimeFormats:{[u.value]:{}}),h=i(be(e.numberFormats)?e.numberFormats:{[u.value]:{}});let m=n?n.missingWarn:Oe(e.missingWarn)||Ir(e.missingWarn)?e.missingWarn:!0,g=n?n.fallbackWarn:Oe(e.fallbackWarn)||Ir(e.fallbackWarn)?e.fallbackWarn:!0,v=n?n.fallbackRoot:Oe(e.fallbackRoot)?e.fallbackRoot:!0,y=!!e.fallbackFormat,S=Ye(e.missing)?e.missing:null,E=Ye(e.missing)?wh(e.missing):null,A=Ye(e.postTranslation)?e.postTranslation:null,x=n?n.warnHtmlMessage:Oe(e.warnHtmlMessage)?e.warnHtmlMessage:!0,O=!!e.escapeParameter;const k=n?n.modifiers:be(e.modifiers)?e.modifiers:{};let P=e.pluralRules||n&&n.pluralRules,$;$=(()=>{s&&ch(null);const L={version:yw,locale:u.value,fallbackLocale:c.value,messages:f.value,modifiers:k,pluralRules:P,missing:E===null?void 0:E,missingWarn:m,fallbackWarn:g,fallbackFormat:y,unresolving:!0,postTranslation:A===null?void 0:A,warnHtmlMessage:x,escapeParameter:O,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};L.datetimeFormats=d.value,L.numberFormats=h.value,L.__datetimeFormatters=be($)?$.__datetimeFormatters:void 0,L.__numberFormatters=be($)?$.__numberFormatters:void 0;const R=uw(L);return s&&ch(R),R})(),wo($,u.value,c.value);function Y(){return[u.value,c.value,f.value,d.value,h.value]}const q=oe({get:()=>u.value,set:L=>{u.value=L,$.locale=u.value}}),le=oe({get:()=>c.value,set:L=>{c.value=L,$.fallbackLocale=c.value,wo($,u.value,L)}}),Ie=oe(()=>f.value),Ce=oe(()=>d.value),ie=oe(()=>h.value);function fe(){return Ye(A)?A:null}function ve(L){A=L,$.postTranslation=L}function je(){return S}function Ee(L){L!==null&&(E=wh(L)),S=L,$.missing=E}const $e=(L,R,ue,me,We,At)=>{Y();let Ht;try{__INTLIFY_PROD_DEVTOOLS__,s||($.fallbackContext=n?cw():void 0),Ht=L($)}finally{__INTLIFY_PROD_DEVTOOLS__,s||($.fallbackContext=void 0)}if(ue!=="translate exists"&&ft(Ht)&&Ht===hl||ue==="translate exists"&&!Ht){const[ki,ys]=R();return n&&v?me(n):We(ki)}else{if(At(Ht))return Ht;throw vt(ht.UNEXPECTED_RETURN_TYPE)}};function xe(...L){return $e(Line truncated
* vue-router v4.3.3
* (c) 2024 Eduardo San Martin Morote
* @license MIT
*/const Os=typeof document<"u";function Yw(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const He=Object.assign;function ql(e,t){const n={};for(const r in t){const s=t[r];n[r]=En(s)?s.map(e):e(s)}return n}const Fo=()=>{},En=Array.isArray,E_=/#/g,Kw=/&/g,qw=/\//g,Gw=/=/g,Xw=/\?/g,w_=/\+/g,Qw=/%5B/g,Jw=/%5D/g,A_=/%5E/g,Zw=/%60/g,T_=/%7B/g,eA=/%7C/g,S_=/%7D/g,tA=/%20/g;function bf(e){return encodeURI(""+e).replace(eA,"|").replace(Qw,"[").replace(Jw,"]")}function nA(e){return bf(e).replace(T_,"{").replace(S_,"}").replace(A_,"^")}function ru(e){return bf(e).replace(w_,"%2B").replace(tA,"+").replace(E_,"%23").replace(Kw,"%26").replace(Zw,"`").replace(T_,"{").replace(S_,"}").replace(A_,"^")}function rA(e){return ru(e).replace(Gw,"%3D")}function sA(e){return bf(e).replace(E_,"%23").replace(Xw,"%3F")}function oA(e){return e==null?"":sA(e).replace(qw,"%2F")}function ni(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const iA=/\/$/,aA=e=>e.replace(iA,"");function Gl(e,t,n="/"){let r,s={},o="",i="";const a=t.indexOf("#");let l=t.indexOf("?");return a<l&&a>=0&&(l=-1),l>-1&&(r=t.slice(0,l),o=t.slice(l+1,a>-1?a:t.length),s=e(o)),a>-1&&(r=r||t.slice(0,a),i=t.slice(a,t.length)),r=fA(r??t,n),{fullPath:r+(o&&"?")+o+i,path:r,query:s,hash:ni(i)}}function lA(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function kh(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function cA(e,t,n){const r=t.matched.length-1,s=n.matched.length-1;return r>-1&&r===s&&Js(t.matched[r],n.matched[s])&&C_(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Js(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function C_(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!uA(e[n],t[n]))return!1;return!0}function uA(e,t){return En(e)?Ih(e,t):En(t)?Ih(t,e):e===t}function Ih(e,t){return En(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function fA(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),s=r[r.length-1];(s===".."||s===".")&&r.push("");let o=n.length-1,i,a;for(i=0;i<r.length;i++)if(a=r[i],a!==".")if(a==="..")o>1&&o--;else break;return n.slice(0,o).join("/")+"/"+r.slice(i).join("/")}var ri;(function(e){e.pop="pop",e.push="push"})(ri||(ri={}));var Vo;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Vo||(Vo={}));function dA(e){if(!e)if(Os){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),aA(e)}const hA=/^[^#]+#/;function mA(e,t){return e.replace(hA,"#")+t}function pA(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const pl=()=>({left:window.scrollX,top:window.scrollY});function gA(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),s=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!s)return;t=pA(s,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function $h(e,t){return(history.state?history.state.position-t:-1)+e}const su=new Map;function _A(e,t){su.set(e,t)}function vA(e){const t=su.get(e);return su.delete(e),t}let bA=()=>location.protocol+"//"+location.host;function O_(e,t){const{pathname:n,search:r,hash:s}=t,o=e.indexOf("#");if(o>-1){let a=s.includes(e.slice(o))?e.slice(o).length:1,l=s.slice(a);return l[0]!=="/"&&(l="/"+l),kh(l,"")}return kh(n,e)+r+s}function yA(e,t,n,r){let s=[],o=[],i=null;const a=({state:d})=>{const h=O_(e,location),m=n.value,g=t.value;let v=0;if(d){if(n.value=h,t.value=d,i&&i===m){i=null;return}v=g?d.position-g.position:0}else r(h);s.forEach(y=>{y(n.value,m,{delta:v,type:ri.pop,direction:v?v>0?Vo.forward:Vo.back:Vo.unknown})})};function l(){i=n.value}function u(d){s.push(d);const h=()=>{const m=s.indexOf(d);m>-1&&s.splice(m,1)};return o.push(h),h}function c(){const{history:d}=window;d.state&&d.replaceState(He({},d.state,{scroll:pl()}),"")}function f(){for(const d of o)d();o=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",c)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",c,{passive:!0}),{pauseListeners:l,listen:u,destroy:f}}function Lh(e,t,n,r=!1,s=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:s?pl():null}}function EA(e){const{history:t,location:n}=window,r={value:O_(e,n)},s={value:t.state};s.value||o(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function o(l,u,c){const f=e.indexOf("#"),d=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+l:bA()+e+l;try{t[c?"replaceState":"pushState"](u,"",d),s.value=u}catch(h){console.error(h),n[c?"replace":"assignLine truncated
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function hT(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var qh=function(){},Sf={},P_={},R_=null,D_={mark:qh,measure:qh};try{typeof window<"u"&&(Sf=window),typeof document<"u"&&(P_=document),typeof MutationObserver<"u"&&(R_=MutationObserver),typeof performance<"u"&&(D_=performance)}catch{}var mT=Sf.navigator||{},Gh=mT.userAgent,Xh=Gh===void 0?"":Gh,$r=Sf,Qe=P_,Qh=R_,Fi=D_;$r.document;var ir=!!Qe.documentElement&&!!Qe.head&&typeof Qe.addEventListener=="function"&&typeof Qe.createElement=="function",M_=~Xh.indexOf("MSIE")||~Xh.indexOf("Trident/"),Vi,Ui,Hi,ji,Bi,Jn="___FONT_AWESOME___",au=16,F_="fa",V_="svg-inline--fa",ds="data-fa-i2svg",lu="data-fa-pseudo-element",pT="data-fa-pseudo-element-pending",Cf="data-prefix",Of="data-icon",Jh="fontawesome-i2svg",gT="async",_T=["HTML","HEAD","STYLE","SCRIPT"],U_=function(){try{return!0}catch{return!1}}(),Ge="classic",rt="sharp",xf=[Ge,rt];function vi(e){return new Proxy(e,{get:function(n,r){return r in n?n[r]:n[Ge]}})}var si=vi((Vi={},gt(Vi,Ge,{fa:"solid",fas:"solid","fa-solid":"solid",far:"regular","fa-regular":"regular",fal:"light","fa-light":"light",fat:"thin","fa-thin":"thin",fad:"duotone","fa-duotone":"duotone",fab:"brands","fa-brands":"brands",fak:"kit",fakd:"kit","fa-kit":"kit","fa-kit-duotone":"kit"}),gt(Vi,rt,{fa:"solid",fass:"solid","fa-solid":"solid",fasr:"regular","fa-regular":"regular",fasl:"light","fa-light":"light",fast:"thin","fa-thin":"thin"}),Vi)),oi=vi((Ui={},gt(Ui,Ge,{solid:"fas",regular:"far",light:"fal",thin:"fat",duotone:"fad",brands:"fab",kit:"fak"}),gt(Ui,rt,{solid:"fass",regular:"fasr",light:"fasl",thin:"fast"}),Ui)),ii=vi((Hi={},gt(Hi,Ge,{fab:"fa-brands",fad:"fa-duotone",fak:"fa-kit",fal:"fa-light",far:"fa-regular",fas:"fa-solid",fat:"fa-thin"}),gt(Hi,rt,{fass:"fa-solid",fasr:"fa-regular",fasl:"fa-light",fast:"fa-thin"}),Hi)),vT=vi((ji={},gt(ji,Ge,{"fa-brands":"fab","fa-duotone":"fad","fa-kit":"fak","fa-light":"fal","fa-regular":"far","fa-solid":"fas","fa-thin":"fat"}),gt(ji,rt,{"fa-solid":"fass","fa-regular":"fasr","fa-light":"fasl","fa-thin":"fast"}),ji)),bT=/fa(s|r|l|t|d|b|k|ss|sr|sl|st)?[\-\ ]/,H_="fa-layers-text",yT=/Font ?Awesome ?([56 ]*)(Solid|Regular|Light|Thin|Duotone|Brands|Free|Pro|Sharp|Kit)?.*/i,ET=vi((Bi={},gt(Bi,Ge,{900:"fas",400:"far",normal:"far",300:"fal",100:"fat"}),gt(Bi,rt,{900:"fass",400:"fasr",300:"fasl",100:"fast"}),Bi)),j_=[1,2,3,4,5,6,7,8,9,10],wT=j_.concat([11,12,13,14,15,16,17,18,19,20]),AT=["class","data-prefix","data-icon","data-fa-transform","data-fa-mask"],ts={GROUP:"duotone-group",SWAP_OPACITY:"swap-opacity",PRIMARY:"primary",SECONDARY:"secondary"},ai=new Set;Object.keys(oi[Ge]).map(ai.add.bind(ai));Object.keys(oi[rt]).map(ai.add.bind(ai));var TT=[].concat(xf,_i(ai),["2xs","xs","sm","lg","xl","2xl","beat","border","fade","beat-fade","bounce","flip-both","flip-horizontal","flip-vertical","flip","fw","inverse","layers-counter","layers-text","layers","li","pull-left","pull-right","pulse","rotate-180","rotate-270","rotate-90","rotate-by","shake","spin-pulse","spin-reverse","spin","stack-1x","stack-2x","stack","ul",ts.GROUP,ts.SWAP_OPACITY,ts.PRIMARY,ts.SECONDARY]).concat(j_.map(function(e){return"".concat(e,"x")})).concat(wT.map(function(e){return"w-".concat(e)})),Uo=$r.FontAwesomeConfig||{};function ST(e){var t=Qe.querySelector("script["+e+"]");if(t)return t.getAttribute(e)}function CT(e){return e===""?!0:e==="false"?!1:e==="true"?!0:e}if(Qe&&typeof Qe.querySelector=="function"){var OT=[["data-family-prefix","familyPrefix"],["data-css-prefix","cssPrefix"],["data-family-default","familyDefault"],["data-style-default","styleDefault"],["data-replacement-class","replacementClass"],["data-auto-replace-svg","autoReplaceSvg"],["data-auto-add-css","autoAddCss"],["data-auto-a11y","autoA11y"],["data-search-pseudo-elements","searchPseudoElements"],["data-observe-mutations","observeMutations"],["data-mutate-approach","mutateApproach"],["data-keep-original-source","keepOriginalSource"],["data-measure-performance","measurePerformance"],["data-show-missing-icons","showMissingIcons"]];OT.forEach(function(e){var t=Tf(e,2),n=t[0],r=t[1],s=CT(ST(n));s!=null&&(Uo[r]=s)})}var B_={styleDefault:"solid",familyDefault:"classic",cssPrefix:F_,replacementClass:V_,autoReplaceSvg:!0,autoAddCss:!0,autoA11y:!0,searchPseudoElements:!1,observeMutations:!0,mutateApproach:"async",keepOriginalSource:!0,measurePerformance:!1,showMissingIcons:!0};Uo.familyPrefix&&(Uo.cssPrefix=Uo.familyPrefix);var eo=se(se({},B_),Uo);eo.autoReplaceSvg||(eo.observeMutations=!1);var ce={};Object.keys(B_).forEach(function(e){Object.defineProperty(ce,e,{enumerable:!0,set:function(n){eo[e]=n,Ho.forEach(function(r){return r(ce)})},get:function(){return eo[e]}})});Object.defineProperty(ce,"familyPrefix",{enumerable:!0,set:function(t){eo.cssPrefix=t,Ho.forEach(function(n){return n(ce)})},get:function(){return eo.cssPrefix}});$r.FontAwesomeConfig=ce;var Ho=[];function xT(e){return Ho.push(e),function(){Ho.splice(Ho.indexOf(e),1)}}var dr=au,Nn={siz Line truncated
--fa-font-solid: normal 900 1em/1 "Font Awesome 6 Solid";
--fa-font-regular: normal 400 1em/1 "Font Awesome 6 Regular";
--fa-font-light: normal 300 1em/1 "Font Awesome 6 Light";
--fa-font-thin: normal 100 1em/1 "Font Awesome 6 Thin";
--fa-font-duotone: normal 900 1em/1 "Font Awesome 6 Duotone";
--fa-font-sharp-solid: normal 900 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-regular: normal 400 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-light: normal 300 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-thin: normal 100 1em/1 "Font Awesome 6 Sharp";
--fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
}
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
overflow: visible;
box-sizing: content-box;
}
.svg-inline--fa {
display: var(--fa-display, inline-block);
height: 1em;
overflow: visible;
vertical-align: -0.125em;
}
.svg-inline--fa.fa-2xs {
vertical-align: 0.1em;
}
.svg-inline--fa.fa-xs {
vertical-align: 0em;
}
.svg-inline--fa.fa-sm {
vertical-align: -0.0714285705em;
}
.svg-inline--fa.fa-lg {
vertical-align: -0.2em;
}
.svg-inline--fa.fa-xl {
vertical-align: -0.25em;
}
.svg-inline--fa.fa-2xl {
vertical-align: -0.3125em;
}
.svg-inline--fa.fa-pull-left {
margin-right: var(--fa-pull-margin, 0.3em);
width: auto;
}
.svg-inline--fa.fa-pull-right {
margin-left: var(--fa-pull-margin, 0.3em);
width: auto;
}
.svg-inline--fa.fa-li {
width: var(--fa-li-width, 2em);
top: 0.25em;
}
.svg-inline--fa.fa-fw {
width: var(--fa-fw-width, 1.25em);
}
.fa-layers svg.svg-inline--fa {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
}
.fa-layers-counter, .fa-layers-text {
display: inline-block;
position: absolute;
text-align: center;
}
.fa-layers {
display: inline-block;
height: 1em;
position: relative;
text-align: center;
vertical-align: -0.125em;
width: 1em;
}
.fa-layers svg.svg-inline--fa {
-webkit-transform-origin: center center;
transform-origin: center center;
}
.fa-layers-text {
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
-webkit-transform-origin: center center;
transform-origin: center center;
}
.fa-layers-counter {
background-color: var(--fa-counter-background-color, #ff253a);
border-radius: var(--fa-counter-border-radius, 1em);
box-sizing: border-box;
color: var(--fa-inverse, #fff);
line-height: var(--fa-counter-line-height, 1);
max-width: var(--fa-counter-max-width, 5em);
min-width: var(--fa-counter-min-width, 1.5em);
overflow: hidden;
padding: var(--fa-counter-padding, 0.25em 0.5em);
right: var(--fa-right, 0);
text-overflow: ellipsis;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
transform: scale(var(--fa-counter-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right;
}
.fa-layers-bottom-right {
bottom: var(--fa-bottom, 0);
right: var(--fa-right, 0);
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom right;
transform-origin: bottom right;
}
.fa-layers-bottom-left {
bottom: var(--fa-bottom, 0);
left: var(--fa-left, 0);
right: auto;
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom left;
transform-origin: bottom left;
}
.fa-layers-top-right {
top: var(--fa-top, 0);
right: var(--fa-right, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right;
}
.fa-layers-top-left {
left: var(--fa-left, 0);
right: auto;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top left;
transform-origin: top left;
}
.fa-1x {
font-size: 1em;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-6x {
font-size: 6em;
}
.fa-7x {
font-size: 7em;
}
.fa-8x {
font-size: 8em;
}
.fa-9x {
font-size: 9em;
}
.fa-10x {
font-size: 10em;
}
.fa-2xs {
font-size: 0.625em;
line-height: 0.1em;
vertical-align: 0.225em;
}
.fa-xs {
font-size: 0.75em;
line-height: 0.0833333337em;
vertical-align: 0.125em;
}
.fa-sm {
font-size: 0.875em;
line-height: 0.0714285718em;
vertical-align: 0.0535714295em;
}
.fa-lg {
font-size: 1.25em;
line-height: 0.05em;
vertical-align: -0.075em;
}
.fa-xl {
font-size: 1.5em;
line-height: 0.0416666682em;
vertical-align: -0.125em;
}
.fa-2xl {
font-size: 2em;
line-height: 0.03125em;
vertical-align: -0.1875em;
}
.fa-fw {
text-align: center;
width: 1.25em;
}
.fa-ul {
list-style-type: none;
margin-left: var(--fa-li-margin, 2.5em);
padding-left: 0;
}
.fa-ul > li {
position: relative;
}
.fa-li {
left: calc(var(--fa-li-width, 2em) * -1);
position: absolute;
text-align: center;
width: var(--fa-li-width, 2em);
line-height: inherit;
}
.fa-border {
border-color: var(--fa-border-color, #eee);
border-radius: var(--fa-border-radius, 0.1em);
border-style: var(--fa-border-style, solid);
border-width: var(--fa-border-width, 0.08em);
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em);
}
.fa-pull-left {
float: left;
margin-right: var(--fa-pull-margin, 0.3em);
}
.fa-pull-right {
float: right;
margin-left: var(--fa-pull-margin, 0.3em);
}
.fa-beat {
-webkit-animation-name: fa-beat;
animation-name: fa-beat;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-bounce {
-webkit-animation-name: fa-bounce;
animation-name: fa-bounce;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
}
.fa-fade {
-webkit-animation-name: fa-fade;
animation-name: fa-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-beat-fade {
-webkit-animation-name: fa-beat-fade;
animation-name: fa-beat-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-flip {
-webkit-animation-name: fa-flip;
animation-name: fa-flip;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-shake {
-webkit-animation-name: fa-shake;
animation-name: fa-shake;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear);
}
.fa-spin {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 2s);
animation-duration: var(--fa-animation-duration, 2s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear);
}
.fa-spin-reverse {
--fa-animation-direction: reverse;
}
.fa-pulse,
.fa-spin-pulse {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
animation-timing-function: var(--fa-animation-timing, steps(8));
}
@media (prefers-reduced-motion: reduce) {
.fa-beat,
.fa-bounce,
.fa-fade,
.fa-beat-fade,
.fa-flip,
.fa-pulse,
.fa-shake,
.fa-spin,
.fa-spin-pulse {
-webkit-animation-delay: -1ms;
animation-delay: -1ms;
-webkit-animation-duration: 1ms;
animation-duration: 1ms;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-transition-delay: 0s;
transition-delay: 0s;
-webkit-transition-duration: 0s;
transition-duration: 0s;
}
}
@-webkit-keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@-webkit-keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
}
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
}
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
}
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
}
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
}
@keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
}
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
}
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
}
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
}
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
}
@-webkit-keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4);
}
}
@keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4);
}
}
@-webkit-keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125));
}
}
@keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125));
}
}
@-webkit-keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
}
}
@keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
}
}
@-webkit-keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg);
}
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg);
}
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg);
}
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg);
}
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg);
}
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg);
}
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg);
}
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg);
}
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg);
}
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg);
}
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg);
}
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg);
}
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg);
}
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg);
}
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg);
}
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg);
}
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.fa-rotate-90 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-webkit-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
-webkit-transform: scale(1, -1);
transform: scale(1, -1);
}
.fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
-webkit-transform: scale(-1, -1);
transform: scale(-1, -1);
}
.fa-rotate-by {
-webkit-transform: rotate(var(--fa-rotate-angle, 0));
transform: rotate(var(--fa-rotate-angle, 0));
}
.fa-stack {
display: inline-block;
vertical-align: middle;
height: 2em;
position: relative;
width: 2.5em;
}
.fa-stack-1x,
.fa-stack-2x {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
z-index: var(--fa-stack-z-index, auto);
}
.svg-inline--fa.fa-stack-1x {
height: 1em;
width: 1.25em;
}
.svg-inline--fa.fa-stack-2x {
height: 2em;
width: 2.5em;
}
.fa-inverse {
color: var(--fa-inverse, #fff);
}
.sr-only,
.fa-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.sr-only-focusable:not(:focus),
.fa-sr-only-focusable:not(:focus) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.svg-inline--fa .fa-primary {
fill: var(--fa-primary-color, currentColor);
opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa .fa-secondary {
fill: var(--fa-secondary-color, currentColor);
opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-primary {
opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-secondary {
opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa mask .fa-primary,
.svg-inline--fa mask .fa-secondary {
fill: black;
}
.fad.fa-inverse,
.fa-duotone.fa-inverse {
color: var(--fa-inverse, #fff);
}`;function z_(){var e=F_,t=V_,n=ce.cssPrefix,r=ce.replacementClass,s=PT;if(n!==e||r!==t){var o=new RegExp("\\.".concat(e,"\\-"),"g"),i=new RegExp("\\--".concat(e,"\\-"),"g"),a=new RegExp("\\.".concat(t),"g");s=s.replace(o,".".concat(n,"-")).replace(i,"--".concat(n,"-")).replace(a,".".concat(r))}return s}var Zh=!1;function Jl(){ce.autoAddCss&&!Zh&&(NT(z_()),Zh=!0)}var RT={mixout:function(){return{dom:{css:z_,insertCss:Jl}}},hooks:function(){return{beforeDOMElementCreation:function(){Jl()},beforeI2svg:function(){Jl()}}}},Zn=$r||{};Zn[Jn]||(Zn[Jn]={});Zn[Jn].styles||(Zn[Jn].styles={});Zn[Jn].hooks||(Zn[Jn].hooks={});Zn[Jn].shims||(Zn[Jn].shims=[]);var vn=Zn[Jn],Y_=[],DT=function e(){Qe.removeEventListener("DOMContentLoaded",e),Da=1,Y_.map(function(t){return t()})},Da=!1;ir&&(Da=(Qe.documentElement.doScroll?/^loaded|^c/:/^loaded|^i|^c/).test(Qe.readyState),Da||Qe.addEventListener("DOMContentLoaded",DT));function MT(e){ir&&(Da?setTimeout(e,0):Y_.push(e))}function bi(e){var t=e.tag,n=e.attributes,r=n===void 0?{}:n,s=e.children,o=s===void 0?[]:s;return typeof e=="string"?W_(e):"<".concat(t," ").concat(IT(r),">").concat(o.map(bi).join(""),"</").concat(t,">")}function em(e,t,n){if(e&&e[t]&&e[t][n])return{prefix:t,iconName:n,icon:e[t][n]}}var Zl=function(t,n,r,s){var o=Object.keys(t),i=o.length,a=n,l,u,c;for(r===void 0?(l=1,c=t[o[0]]):(l=0,c=r);l<i;l++)u=o[l],c=a(c,t[u],u,t);return c};function FT(e){for(var t=[],n=0,r=e.length;n<r;){var s=e.charCodeAt(n++);if(s>=55296&&s<=56319&&n<r){var o=e.charCodeAt(n++);(o&64512)==56320?t.push(((s&1023)<<10)+(o&1023)+65536):(t.push(s),n--)}else t.push(s)}return t}function cu(e){var t=FT(e);return t.length===1?t[0].toString(16):null}function VT(e,t){var n=e.length,r=e.charCodeAt(t),s;return r>=55296&&r<=56319&&n>t+1&&(s=e.charCodeAt(t+1),s>=56320&&s<=57343)?(r-55296)*1024+s-56320+65536:r}function tm(e){return Object.keys(e).reduce(function(t,n){var r=e[n],s=!!r.icon;return s?t[r.iconName]=r.icon:t[n]=r,t},{})}function uu(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.skipHooks,s=r===void 0?!1:r,o=tm(t);typeof vn.hooks.addPack=="function"&&!s?vn.hooks.addPack(e,tm(t)):vn.styles[e]=se(se({},vn.styles[e]||{}),o),e==="fas"&&uu("fa",t)}var Wi,zi,Yi,Ls=vn.styles,UT=vn.shims,HT=(Wi={},gt(Wi,Ge,Object.values(ii[Ge])),gt(Wi,rt,Object.values(ii[rt])),Wi),If=null,K_={},q_={},G_={},X_={},Q_={},jT=(zi={},gt(zi,Ge,Object.keys(si[Ge])),gt(zi,rt,Object.keys(si[rt])),zi);function BT(e){return~TT.indexOf(e)}function WT(e,t){var n=t.split("-"),r=n[0],s=n.slice(1).join("-");return r===e&&s!==""&&!BT(s)?s:null}var J_=function(){var t=function(o){return Zl(Ls,function(i,a,l){return i[l]=Zl(a,o,{}),i},{})};K_=t(function(s,o,i){if(o[3]&&(s[o[3]]=i),o[2]){var a=o[2].filter(function(l){return typeof l=="number"});a.forEach(function(l){s[l.toString(16)]=i})}return s}),q_=t(function(s,o,i){if(s[i]=i,o[2]){var a=o[2].filter(function(l){return typeof l=="string"});a.forEach(function(l){s[l]=i})}return s}),Q_=t(function(s,o,i){var a=o[2];return s[i]=i,a.forEach(function(l){s[l]=i}),s});var n="far"in Ls||ce.autoFetchSvg,r=Zl(UT,function(s,o){var i=o[0],a=o[1],l=o[2];return a==="far"&&!n&&(a="fas"),typeof i=="string"&&(s.names[i]={prefix:a,iconName:l}),typeof i=="number"&&(s.unicodes[i.toString(16)]={prefix:a,iconName:l}),s},{names:{},unicodes:{}});G_=r.names,X_=r.unicodes,If=yl(ce.styleDefault,{family:ce.familyDefault})};xT(function(e){If=yl(e.styleDefault,{family:ce.familyDefault})});J_();function $f(e,t){return(K_[e]||{})[t]}function zT(e,t){return(q_[e]||{})[t]}function ns(e,t){return(Q_[e]||{})[t]}function Z_(e){return G_[e]||{prefix:null,iconName:null}}function YT(e){var t=X_[e],n=$f("fas",e);return t||(n?{prefix:"fas",iconName:n}:null)||{prefix:null,iconName:null}}function Lr(){return If}var Lf=function(){return{prefix:null,iconName:null,rest:[]}};function yl(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.family,r=n===void 0?Ge:n,s=si[r][e],o=oi[r][e]||oi[r][s],i=e in vn.styles?e:null;return o||i||null}var nm=(Yi={},gt(Yi,Ge,Object.keys(ii[Ge])),gt(Yi,rt,Object.keys(ii[rt])),Yi);function El(e){var t,n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.skipLookups,s=r===void 0?!1:r,o=(t={},gt(t,Ge,"".concat(ce.cssPrefix,"-").concat(Ge)),gt(t,rt,"".concat(ce.cssPrefix,"-").concat(rt)),t),i=null,a=Ge;(e.includes(o[Ge])||e.some(function(u){return nm[Ge].includes(u)}))&&(a=Ge),(e.includes(o[rt])||e.some(function(u){return nm[rt].includes(u)}))&&(a=rt);var l=e.reduce(function(u,c){var f=WT(ce.cssPrefix,c);if(Ls[c]?(c=HT[a].includes(c)?vT[a][c]:c,i=c,u.prefix=c):jT[a].indexOf(c)>-1?(i=c,u.prefix=yl(c,{family:a})):f?u.iconName=f:c!==ce.replacementClass&&c!==o[Ge]&&c!==o[rt]&&u.rest.push(c),!s&&u.prefix&&u.iconName){var d=i==="fa"?Z_(u.iconName):{},h=ns(u.prefix,u.iconName);d.prefix&&(i=null),u.iconName=d.iconName||h||u.iconName,u.prefix=d.prefix||u.prefix,u.prefix==="far"&&!Ls.far&&Ls.fas&&!ce.autoFetchSvg&&(u.prefix="fas")}return u},Lf());return(e.inc Line truncated
`);n.setAttribute(ds,""),n.innerHTML=i}};function am(e){e()}function rv(e,t){var n=typeof t=="function"?t:da;if(e.length===0)n();else{var r=am;ce.mutateApproach===gT&&(r=$r.requestAnimationFrame||am),r(function(){var s=lS(),o=Rf.begin("mutate");e.map(s),o(),n()})}}var Df=!1;function sv(){Df=!0}function gu(){Df=!1}var Ma=null;function lm(e){if(Qh&&ce.observeMutations){var t=e.treeCallback,n=t===void 0?da:t,r=e.nodeCallback,s=r===void 0?da:r,o=e.pseudoElementsCallback,i=o===void 0?da:o,a=e.observeMutationsRoot,l=a===void 0?Qe:a;Ma=new Qh(function(u){if(!Df){var c=Lr();ho(u).forEach(function(f){if(f.type==="childList"&&f.addedNodes.length>0&&!im(f.addedNodes[0])&&(ce.searchPseudoElements&&i(f.target),n(f.target)),f.type==="attributes"&&f.target.parentNode&&ce.searchPseudoElements&&i(f.target.parentNode),f.type==="attributes"&&im(f.target)&&~AT.indexOf(f.attributeName))if(f.attributeName==="class"&&iS(f.target)){var d=El(Nf(f.target)),h=d.prefix,m=d.iconName;f.target.setAttribute(Cf,h||c),m&&f.target.setAttribute(Of,m)}else aS(f.target)&&s(f.target)})}}),ir&&Ma.observe(l,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}}function dS(){Ma&&Ma.disconnect()}function hS(e){var t=e.getAttribute("style"),n=[];return t&&(n=t.split(";").reduce(function(r,s){var o=s.split(":"),i=o[0],a=o.slice(1);return i&&a.length>0&&(r[i]=a.join(":").trim()),r},{})),n}function mS(e){var t=e.getAttribute("data-prefix"),n=e.getAttribute("data-icon"),r=e.innerText!==void 0?e.innerText.trim():"",s=El(Nf(e));return s.prefix||(s.prefix=Lr()),t&&n&&(s.prefix=t,s.iconName=n),s.iconName&&s.prefix||(s.prefix&&r.length>0&&(s.iconName=zT(s.prefix,e.innerText)||$f(s.prefix,cu(e.innerText))),!s.iconName&&ce.autoFetchSvg&&e.firstChild&&e.firstChild.nodeType===Node.TEXT_NODE&&(s.iconName=e.firstChild.data)),s}function pS(e){var t=ho(e.attributes).reduce(function(s,o){return s.name!=="class"&&s.name!=="style"&&(s[o.name]=o.value),s},{}),n=e.getAttribute("title"),r=e.getAttribute("data-fa-title-id");return ce.autoA11y&&(n?t["aria-labelledby"]="".concat(ce.replacementClass,"-title-").concat(r||li()):(t["aria-hidden"]="true",t.focusable="false")),t}function gS(){return{iconName:null,title:null,titleId:null,prefix:null,transform:Nn,symbol:!1,mask:{iconName:null,prefix:null,rest:[]},maskId:null,extra:{classes:[],styles:{},attributes:{}}}}function cm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{styleParser:!0},n=mS(e),r=n.iconName,s=n.prefix,o=n.rest,i=pS(e),a=fu("parseNodeAttributes",{},e),l=t.styleParser?hS(e):[];return se({iconName:r,title:e.getAttribute("title"),titleId:e.getAttribute("data-fa-title-id"),prefix:s,transform:Nn,mask:{iconName:null,prefix:null,rest:[]},maskId:null,symbol:!1,extra:{classes:o,styles:l,attributes:i}},a)}var _S=vn.styles;function ov(e){var t=ce.autoReplaceSvg==="nest"?cm(e,{styleParser:!1}):cm(e);return~t.extra.classes.indexOf(H_)?er("generateLayersText",e,t):er("generateSvgReplacementMutation",e,t)}var Pr=new Set;xf.map(function(e){Pr.add("fa-".concat(e))});Object.keys(si[Ge]).map(Pr.add.bind(Pr));Object.keys(si[rt]).map(Pr.add.bind(Pr));Pr=_i(Pr);function um(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;if(!ir)return Promise.resolve();var n=Qe.documentElement.classList,r=function(f){return n.add("".concat(Jh,"-").concat(f))},s=function(f){return n.remove("".concat(Jh,"-").concat(f))},o=ce.autoFetchSvg?Pr:xf.map(function(c){return"fa-".concat(c)}).concat(Object.keys(_S));o.includes("fa")||o.push("fa");var i=[".".concat(H_,":not([").concat(ds,"])")].concat(o.map(function(c){return".".concat(c,":not([").concat(ds,"])")})).join(", ");if(i.length===0)return Promise.resolve();var a=[];try{a=ho(e.querySelectorAll(i))}catch{}if(a.length>0)r("pending"),s("complete");else return Promise.resolve();var l=Rf.begin("onTree"),u=a.reduce(function(c,f){try{var d=ov(f);d&&c.push(d)}catch(h){U_||h.name==="MissingIcon"&&console.error(h)}return c},[]);return new Promise(function(c,f){Promise.all(u).then(function(d){rv(d,function(){r("active"),r("complete"),s("pending"),typeof t=="function"&&t(),l(),c()})}).catch(function(d){l(),f(d)})})}function vS(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;ov(e).then(function(n){n&&rv([n],t)})}function bS(e){return function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=(t||{}).icon?t:du(t||{}),s=n.mask;return s&&(s=(s||{}).icon?s:du(s||{})),e(r,se(se({},n),{},{mask:s}))}}var yS=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.transform,s=r===void 0?Nn:r,o=n.symbol,i=o===void 0?!1:o,a=n.mask,l=a===void 0?null:a,u=n.maskId,c=u===void 0?null:u,f=n.title,d=f===void 0?null:f,h=n.titleId,m=h===void 0?null:h,g=n.classes,v=g===void 0?[]:g,y=n.attributes,S=y===void 0?{}:y,E=n.styles,A=E===void 0?{}:E;if(t){var x=t.prefix,O=t.iconName,k=t.icon;return wl(se({type:"icon"},t),function(){return hs("beforeDOMElementCreation",{iconDefinition:t,params:n}),ce.autoA11y&&(d?S["aria-labelledby"]="".con Line truncated
`),e.removeAttribute(n),r()}).catch(s)}else r()}else r()})}function OS(e){return Promise.all([dm(e,"::before"),dm(e,"::after")])}function xS(e){return e.parentNode!==document.head&&!~_T.indexOf(e.tagName.toUpperCase())&&!e.getAttribute(lu)&&(!e.parentNode||e.parentNode.tagName!=="svg")}function hm(e){if(ir)return new Promise(function(t,n){var r=ho(e.querySelectorAll("*")).filter(xS).map(OS),s=Rf.begin("searchPseudoElements");sv(),Promise.all(r).then(function(){s(),gu(),t()}).catch(function(){s(),gu(),n()})})}var NS={hooks:function(){return{mutationObserverCallbacks:function(n){return n.pseudoElementsCallback=hm,n}}},provides:function(t){t.pseudoElements2svg=function(n){var r=n.node,s=r===void 0?Qe:r;ce.searchPseudoElements&&hm(s)}}},mm=!1,kS={mixout:function(){return{dom:{unwatch:function(){sv(),mm=!0}}}},hooks:function(){return{bootstrap:function(){lm(fu("mutationObserverCallbacks",{}))},noAuto:function(){dS()},watch:function(n){var r=n.observeMutationsRoot;mm?gu():lm(fu("mutationObserverCallbacks",{observeMutationsRoot:r}))}}}},pm=function(t){var n={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return t.toLowerCase().split(" ").reduce(function(r,s){var o=s.toLowerCase().split("-"),i=o[0],a=o.slice(1).join("-");if(i&&a==="h")return r.flipX=!0,r;if(i&&a==="v")return r.flipY=!0,r;if(a=parseFloat(a),isNaN(a))return r;switch(i){case"grow":r.size=r.size+a;break;case"shrink":r.size=r.size-a;break;case"left":r.x=r.x-a;break;case"right":r.x=r.x+a;break;case"up":r.y=r.y-a;break;case"down":r.y=r.y+a;break;case"rotate":r.rotate=r.rotate+a;break}return r},n)},IS={mixout:function(){return{parse:{transform:function(n){return pm(n)}}}},hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-transform");return s&&(n.transform=pm(s)),n}}},provides:function(t){t.generateAbstractTransformGrouping=function(n){var r=n.main,s=n.transform,o=n.containerWidth,i=n.iconWidth,a={transform:"translate(".concat(o/2," 256)")},l="translate(".concat(s.x*32,", ").concat(s.y*32,") "),u="scale(".concat(s.size/16*(s.flipX?-1:1),", ").concat(s.size/16*(s.flipY?-1:1),") "),c="rotate(".concat(s.rotate," 0 0)"),f={transform:"".concat(l," ").concat(u," ").concat(c)},d={transform:"translate(".concat(i/2*-1," -256)")},h={outer:a,inner:f,path:d};return{tag:"g",attributes:se({},h.outer),children:[{tag:"g",attributes:se({},h.inner),children:[{tag:r.icon.tag,children:r.icon.children,attributes:se(se({},r.icon.attributes),h.path)}]}]}}}},tc={x:0,y:0,width:"100%",height:"100%"};function gm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return e.attributes&&(e.attributes.fill||t)&&(e.attributes.fill="black"),e}function $S(e){return e.tag==="g"?e.children:[e]}var LS={hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-mask"),o=s?El(s.split(" ").map(function(i){return i.trim()})):Lf();return o.prefix||(o.prefix=Lr()),n.mask=o,n.maskId=r.getAttribute("data-fa-mask-id"),n}}},provides:function(t){t.generateAbstractMask=function(n){var r=n.children,s=n.attributes,o=n.main,i=n.mask,a=n.maskId,l=n.transform,u=o.width,c=o.icon,f=i.width,d=i.icon,h=$T({transform:l,containerWidth:f,iconWidth:u}),m={tag:"rect",attributes:se(se({},tc),{},{fill:"white"})},g=c.children?{children:c.children.map(gm)}:{},v={tag:"g",attributes:se({},h.inner),children:[gm(se({tag:c.tag,attributes:se(se({},c.attributes),h.path)},g))]},y={tag:"g",attributes:se({},h.outer),children:[v]},S="mask-".concat(a||li()),E="clip-".concat(a||li()),A={tag:"mask",attributes:se(se({},tc),{},{id:S,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[m,y]},x={tag:"defs",children:[{tag:"clipPath",attributes:{id:E},children:$S(d)},A]};return r.push(x,{tag:"rect",attributes:se({fill:"currentColor","clip-path":"url(#".concat(E,")"),mask:"url(#".concat(S,")")},tc)}),{children:r,attributes:s}}}},PS={provides:function(t){var n=!1;$r.matchMedia&&(n=$r.matchMedia("(prefers-reduced-motion: reduce)").matches),t.missingIconAbstract=function(){var r=[],s={fill:"currentColor"},o={attributeType:"XML",repeatCount:"indefinite",dur:"2s"};r.push({tag:"path",attributes:se(se({},s),{},{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1 Line truncated
`).forEach(function(i){s=i.indexOf(":"),n=i.substring(0,s).trim().toLowerCase(),r=i.substring(s+1).trim(),!(!n||t[n]&&o2[n])&&(n==="set-cookie"?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t},Sm=Symbol("internals");function To(e){return e&&String(e).trim().toLowerCase()}function pa(e){return e===!1||e==null?e:D.isArray(e)?e.map(pa):String(e)}function a2(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}const l2=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function sc(e,t,n,r,s){if(D.isFunction(r))return r.call(this,t,n);if(s&&(t=n),!!D.isString(t)){if(D.isString(r))return t.indexOf(r)!==-1;if(D.isRegExp(r))return r.test(t)}}function c2(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,n,r)=>n.toUpperCase()+r)}function u2(e,t){const n=D.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(s,o,i){return this[r].call(this,t,s,o,i)},configurable:!0})})}let Vt=class{constructor(t){t&&this.set(t)}set(t,n,r){const s=this;function o(a,l,u){const c=To(l);if(!c)throw new Error("header name must be a non-empty string");const f=D.findKey(s,c);(!f||s[f]===void 0||u===!0||u===void 0&&s[f]!==!1)&&(s[f||l]=pa(a))}const i=(a,l)=>D.forEach(a,(u,c)=>o(u,c,l));if(D.isPlainObject(t)||t instanceof this.constructor)i(t,n);else if(D.isString(t)&&(t=t.trim())&&!l2(t))i(i2(t),n);else if(D.isHeaders(t))for(const[a,l]of t.entries())o(l,a,r);else t!=null&&o(n,t,r);return this}get(t,n){if(t=To(t),t){const r=D.findKey(this,t);if(r){const s=this[r];if(!n)return s;if(n===!0)return a2(s);if(D.isFunction(n))return n.call(this,s,r);if(D.isRegExp(n))return n.exec(s);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,n){if(t=To(t),t){const r=D.findKey(this,t);return!!(r&&this[r]!==void 0&&(!n||sc(this,this[r],r,n)))}return!1}delete(t,n){const r=this;let s=!1;function o(i){if(i=To(i),i){const a=D.findKey(r,i);a&&(!n||sc(r,r[a],a,n))&&(delete r[a],s=!0)}}return D.isArray(t)?t.forEach(o):o(t),s}clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const o=n[r];(!t||sc(this,this[o],o,t,!0))&&(delete this[o],s=!0)}return s}normalize(t){const n=this,r={};return D.forEach(this,(s,o)=>{const i=D.findKey(r,o);if(i){n[i]=pa(s),delete n[o];return}const a=t?c2(o):String(o).trim();a!==o&&delete n[o],n[a]=pa(s),r[a]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const n=Object.create(null);return D.forEach(this,(r,s)=>{r!=null&&r!==!1&&(n[s]=t&&D.isArray(r)?r.join(", "):r)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).join(`
`)}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}static accessor(t){const r=(this[Sm]=this[Sm]={accessors:{}}).accessors,s=this.prototype;function o(i){const a=To(i);r[a]||(u2(s,i),r[a]=!0)}return D.isArray(t)?t.forEach(o):o(t),this}};Vt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);D.reduceDescriptors(Vt.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});D.freezeMethods(Vt);function oc(e,t){const n=this||Ei,r=t||n,s=Vt.from(r.headers);let o=r.data;return D.forEach(e,function(a){o=a.call(n,o,s.normalize(),t?t.status:void 0)}),s.normalize(),o}function Tv(e){return!!(e&&e.__CANCEL__)}function po(e,t,n){we.call(this,e??"canceled",we.ERR_CANCELED,t,n),this.name="CanceledError"}D.inherits(po,we,{__CANCEL__:!0});function Sv(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new we("Request failed with status code "+n.status,[we.ERR_BAD_REQUEST,we.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function f2(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function d2(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,o=0,i;return t=t!==void 0?t:1e3,function(l){const u=Date.now(),c=r[o];i||(i=u),n[s]=l,r[s]=u;let f=o,d=0;for(;f!==s;)d+=n[f++],f=f%e;if(s=(s+1)%e,s===o&&(o=(o+1)%e),u-i<t)return;const h=c&&u-c;return h?Math.round(d*1e3/h):void 0}}function h2(e,t){let n=0,r=1e3/t,s,o;const i=(u,c=Date.now())=>{n=c,s=null,o&&(clearTimeout(o),o=null),e.apply(null,u)};return[(...u)=>{const c=Date.now(),f=c-n;f>=r?i(u,c):(s=u,o||(o=setTimeout(()=>{o=null,i(s)},r-f)))},()=>s&&i(s)]}const Va=(e,t,n=3)=>{let r=0;const s=d2(50,250);return h2(o=>{const i=o.loaded,a=o.lengthComputable?o.total:void 0,l=i-r,u=s(l),c=i<=a;r=i;const f={loaded:i,total:a,progress:a?i/a:void 0,bytes:l,rate:u||void 0,estimated:u&&a&&c?(a-i)/u:void 0,event:o,lengthComputable:a!=null,[t?"download":"upload"]:!0};e(f)},n)},Cm=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},Om=e=>(...t)=>D.asap(()=>e(...t)),m2=Gt.hasStandardBrowserEnv?function(){const t=Gt.navigator&&/(msie|trident)/i.test(Gt.navigator.userAgent),n=document.createElement("a");let r;function s(o){let i=o;return t&&(n.setAttribute("href",i),i=n.href),n.setAttribute("href",i),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:n.pathname.charAt(0)==="/"?n.pathname:"/"+n.pathname}}return r=s(window.location.href),function(i){const a=D.isString(i)?s(i):i;return a.protocol===r.protocol&&a.host===r.host}}():function(){return function(){return!0}}(),p2=Gt.hasStandardBrowserEnv?{write(e,t,n,r,s,o){const i=[e+"="+encodeURIComponent(t)];D.isNumber(n)&&i.push("expires="+new Date(n).toGMTString()),D.isString(r)&&i.push("path="+r),D.isString(s)&&i.push("domain="+s),o===!0&&i.push("secure"),document.cookie=i.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read(){return null},remove(){}};function g2(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function _2(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function Cv(e,t){return e&&!g2(t)?_2(e,t):t}const xm=e=>e instanceof Vt?{...e}:e;function ms(e,t){t=t||{};const n={};function r(u,c,f){return D.isPlainObject(u)&&D.isPlainObject(c)?D.merge.call({caseless:f},u,c):D.isPlainObject(c)?D.merge({},c):D.isArray(c)?c.slice():c}function s(u,c,f){if(D.isUndefined(c)){if(!D.isUndefined(u))return r(void 0,u,f)}else return r(u,c,f)}function o(u,c){if(!D.isUndefined(c))return r(void 0,c)}function i(u,c){if(D.isUndefined(c)){if(!D.isUndefined(u))return r(void 0,u)}else return r(void 0,c)}function a(u,c,f){if(f in t)return r(u,c);if(f in e)return r(void 0,u)}const l={url:o,method:o,data:o,baseURL:i,transformRequest:i,transformResponse:i,paramsSerializer:i,timeout:i,timeoutMessage:i,withCredentials:i,withXSRFToken:i,adapter:i,responseType:i,xsrfCookieName:i,xsrfHeaderName:i,onUploadProgress:i,onDownloadProgress:i,decompress:i,maxContentLength:i,maxBodyLength:i,beforeRedirect:i,transport:i,httpAgent:i,httpsAgent:i,cancelToken:i,socketPath:i,responseEncoding:i,validateStatus:a,headers:(u,c)=>s(xm(u),xm(c),!0)};return D.forEach(Object.keys(Object.assign({},e,t)),function(c){const f=l[c]||s,d=f(e[c],t[c],c);D.isUndefined(d)&&f!==a||(n[c]=d)}),n}const Ov=e=>{const t=ms({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:s,xsrfCookieName:o,headers:i,auth:a}=t;t.headers=i=Vt.from(i),t.url=Ev(Cv(t.baseURL,t.url),e.params,e.paramsSerializer),a&&i.set("Authorization","Basic "+btoa((a.username||"")+":"+(a.password?unescape(encodeURIComponent(a.password)):""))); Line truncated
`+o.map(Im).join(`
`):" "+Im(o[0]):"as no adapter specified";throw new we("There is no suitable adapter to dispatch the request "+i,"ERR_NOT_SUPPORT")}return r},adapters:Au};function ic(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new po(null,e)}function $m(e){return ic(e),e.headers=Vt.from(e.headers),e.data=oc.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),kv.getAdapter(e.adapter||Ei.adapter)(e).then(function(r){return ic(e),r.data=oc.call(e,e.transformResponse,r),r.headers=Vt.from(r.headers),r},function(r){return Tv(r)||(ic(e),r&&r.response&&(r.response.data=oc.call(e,e.transformResponse,r.response),r.response.headers=Vt.from(r.response.headers))),Promise.reject(r)})}const Iv="1.7.5",Uf={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{Uf[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Lm={};Uf.transitional=function(t,n,r){function s(o,i){return"[Axios v"+Iv+"] Transitional option '"+o+"'"+i+(r?". "+r:"")}return(o,i,a)=>{if(t===!1)throw new we(s(i," has been removed"+(n?" in "+n:"")),we.ERR_DEPRECATED);return n&&!Lm[i]&&(Lm[i]=!0,console.warn(s(i," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(o,i,a):!0}};function x2(e,t,n){if(typeof e!="object")throw new we("options must be an object",we.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let s=r.length;for(;s-- >0;){const o=r[s],i=t[o];if(i){const a=e[o],l=a===void 0||i(a,o,e);if(l!==!0)throw new we("option "+o+" must be "+l,we.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new we("Unknown option "+o,we.ERR_BAD_OPTION)}}const Tu={assertOptions:x2,validators:Uf},hr=Tu.validators;let cs=class{constructor(t){this.defaults=t,this.interceptors={request:new Tm,response:new Tm}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let s;Error.captureStackTrace?Error.captureStackTrace(s={}):s=new Error;const o=s.stack?s.stack.replace(/^.+\n/,""):"";try{r.stack?o&&!String(r.stack).endsWith(o.replace(/^.+\n.+\n/,""))&&(r.stack+=`
`+o):r.stack=o}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=ms(this.defaults,n);const{transitional:r,paramsSerializer:s,headers:o}=n;r!==void 0&&Tu.assertOptions(r,{silentJSONParsing:hr.transitional(hr.boolean),forcedJSONParsing:hr.transitional(hr.boolean),clarifyTimeoutError:hr.transitional(hr.boolean)},!1),s!=null&&(D.isFunction(s)?n.paramsSerializer={serialize:s}:Tu.assertOptions(s,{encode:hr.function,serialize:hr.function},!0)),n.method=(n.method||this.defaults.method||"get").toLowerCase();let i=o&&D.merge(o.common,o[n.method]);o&&D.forEach(["delete","get","head","post","put","patch","common"],m=>{delete o[m]}),n.headers=Vt.concat(i,o);const a=[];let l=!0;this.interceptors.request.forEach(function(g){typeof g.runWhen=="function"&&g.runWhen(n)===!1||(l=l&&g.synchronous,a.unshift(g.fulfilled,g.rejected))});const u=[];this.interceptors.response.forEach(function(g){u.push(g.fulfilled,g.rejected)});let c,f=0,d;if(!l){const m=[$m.bind(this),void 0];for(m.unshift.apply(m,a),m.push.apply(m,u),d=m.length,c=Promise.resolve(n);f<d;)c=c.then(m[f++],m[f++]);return c}d=a.length;let h=n;for(f=0;f<d;){const m=a[f++],g=a[f++];try{h=m(h)}catch(v){g.call(this,v);break}}try{c=$m.call(this,h)}catch(m){return Promise.reject(m)}for(f=0,d=u.length;f<d;)c=c.then(u[f++],u[f++]);return c}getUri(t){t=ms(this.defaults,t);const n=Cv(t.baseURL,t.url);return Ev(n,t.params,t.paramsSerializer)}};D.forEach(["delete","get","head","options"],function(t){cs.prototype[t]=function(n,r){return this.request(ms(r||{},{method:t,url:n,data:(r||{}).data}))}});D.forEach(["post","put","patch"],function(t){function n(r){return function(o,i,a){return this.request(ms(a||{},{method:t,headers:r?{"Content-Type":"multipart/form-data"}:{},url:o,data:i}))}}cs.prototype[t]=n(),cs.prototype[t+"Form"]=n(!0)});let N2=class $v{constructor(t){if(typeof t!="function")throw new TypeError("executor must be a function.");let n;this.promise=new Promise(function(o){n=o});const r=this;this.promise.then(s=>{if(!r._listeners)return;let o=r._listeners.length;for(;o-- >0;)r._listeners[o](s);r._listeners=null}),this.promise.then=s=>{let o;const i=new Promise(a=>{r.subscribe(a),o=a}).then(s);return i.cancel=function(){r.unsubscribe(o)},i},t(function(o,i,a){r.reason||(r.reason=new po(o,i,a),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}static source(){let t;return{token:new $v(function(s){t=s}),cancel:t}}};function k2(e){return function(n){return e.apply(null,n)}}function I2(e){return D.isObject(e)&&e.isAxiosError===!0}const Su={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Su).forEach(([e,t])=>{Su[t]=e});function Lv(e){const t=new cs(e),n=cv(cs.prototype.request,t);return D.extend(n,cs.prototype,t,{allOwnKeys:!0}),D.extend(n,t,null,{allOwnKeys:!0}),n.create=function(s){return Lv(ms(e,s))},n}const Ve=Lv(Ei);Ve.Axios=cs;Ve.CanceledError=po;Ve.CancelToken=N2;Ve.isCancel=Tv;Ve.VERSION=Iv;Ve.toFormData=Cl;Ve.AxiosError=we;Ve.Cancel=Ve.CanceledError;Ve.all=function(t){return Promise.all(t)};Ve.spread=k2;Ve.isAxiosError=I2;Ve.mergeConfig=ms;Ve.AxiosHeaders=Vt;Ve.formToJSON=e=>Av(D.isHTMLForm(e)?new FormData(e):e);Ve.getAdapter=kv.getAdapter;Ve.HttpStatusCode=Su;Ve.default=Ve;const{Axios:ZM,AxiosError:$2,CanceledError:e6,isCancel:t6,CancelToken:n6,VERSION:r6,all:s6,Cancel:o6,isAxiosError:i6,spread:a6,toFormData:l6,AxiosHeaders:c6,HttpStatusCode:u6,formToJSON:f6,getAdapter:d6,mergeConfig:h6}=Ve;class L2{signupUser(t){return new Promise((n,r)=>{Ve.post(`${pn.API_BASE_URL}/auth/signup`,t,{withCredentials:!0}).then(s=>{n(s.data)}).catch(s=>{r(s)})})}loginUser(t){return new Pr Line truncated
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/const mr=new Map,ac={set(e,t,n){mr.has(e)||mr.set(e,new Map);const r=mr.get(e);if(!r.has(t)&&r.size!==0){console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(r.keys())[0]}.`);return}r.set(t,n)},get(e,t){return mr.has(e)&&mr.get(e).get(t)||null},remove(e,t){if(!mr.has(e))return;const n=mr.get(e);n.delete(t),n.size===0&&mr.delete(e)}},FO=1e6,VO=1e3,Nu="transitionend",ib=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,(t,n)=>`#${CSS.escape(n)}`)),e),UO=e=>e==null?`${e}`:Object.prototype.toString.call(e).match(/\s([a-z]+)/i)[1].toLowerCase(),HO=e=>{do e+=Math.floor(Math.random()*FO);while(document.getElementById(e));return e},jO=e=>{if(!e)return 0;let{transitionDuration:t,transitionDelay:n}=window.getComputedStyle(e);const r=Number.parseFloat(t),s=Number.parseFloat(n);return!r&&!s?0:(t=t.split(",")[0],n=n.split(",")[0],(Number.parseFloat(t)+Number.parseFloat(n))*VO)},ab=e=>{e.dispatchEvent(new Event(Nu))},Kn=e=>!e||typeof e!="object"?!1:(typeof e.jquery<"u"&&(e=e[0]),typeof e.nodeType<"u"),Rr=e=>Kn(e)?e.jquery?e[0]:e:typeof e=="string"&&e.length>0?document.querySelector(ib(e)):null,vo=e=>{if(!Kn(e)||e.getClientRects().length===0)return!1;const t=getComputedStyle(e).getPropertyValue("visibility")==="visible",n=e.closest("details:not([open])");if(!n)return t;if(n!==e){const r=e.closest("summary");if(r&&r.parentNode!==n||r===null)return!1}return t},Dr=e=>!e||e.nodeType!==Node.ELEMENT_NODE||e.classList.contains("disabled")?!0:typeof e.disabled<"u"?e.disabled:e.hasAttribute("disabled")&&e.getAttribute("disabled")!=="false",lb=e=>{if(!document.documentElement.attachShadow)return null;if(typeof e.getRootNode=="function"){const t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?lb(e.parentNode):null},ja=()=>{},Ai=e=>{e.offsetHeight},cb=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,lc=[],BO=e=>{document.readyState==="loading"?(lc.length||document.addEventListener("DOMContentLoaded",()=>{for(const t of lc)t()}),lc.push(e)):e()},ln=()=>document.documentElement.dir==="rtl",un=e=>{BO(()=>{const t=cb();if(t){const n=e.NAME,r=t.fn[n];t.fn[n]=e.jQueryInterface,t.fn[n].Constructor=e,t.fn[n].noConflict=()=>(t.fn[n]=r,e.jQueryInterface)}})},Ft=(e,t=[],n=e)=>typeof e=="function"?e(...t):n,ub=(e,t,n=!0)=>{if(!n){Ft(e);return}const s=jO(t)+5;let o=!1;const i=({target:a})=>{a===t&&(o=!0,t.removeEventListener(Nu,i),Ft(e))};t.addEventListener(Nu,i),setTimeout(()=>{o||ab(t)},s)},ed=(e,t,n,r)=>{const s=e.length;let o=e.indexOf(t);return o===-1?!n&&r?e[s-1]:e[0]:(o+=n?1:-1,r&&(o=(o+s)%s),e[Math.max(0,Math.min(o,s-1))])},WO=/[^.]*(?=\..*)\.|.*/,zO=/\..*/,YO=/::\d+$/,cc={};let jm=1;const fb={mouseenter:"mouseover",mouseleave:"mouseout"},KO=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function db(e,t){return t&&`${t}::${jm++}`||e.uidEvent||jm++}function hb(e){const t=db(e);return e.uidEvent=t,cc[t]=cc[t]||{},cc[t]}function qO(e,t){return function n(r){return td(r,{delegateTarget:e}),n.oneOff&&z.off(e,r.type,t),t.apply(e,[r])}}function GO(e,t,n){return function r(s){const o=e.querySelectorAll(t);for(let{target:i}=s;i&&i!==this;i=i.parentNode)for(const a of o)if(a===i)return td(s,{delegateTarget:i}),r.oneOff&&z.off(e,s.type,t,n),n.apply(i,[s])}}function mb(e,t,n=null){return Object.values(e).find(r=>r.callable===t&&r.delegationSelector===n)}function pb(e,t,n){const r=typeof t=="string",s=r?n:t||n;let o=gb(e);return KO.has(o)||(o=e),[r,s,o]}function Bm(e,t,n,r,s){if(typeof t!="string"||!e)return;let[o,i,a]=pb(t,n,r);t in fb&&(i=(m=>function(g){if(!g.relatedTarget||g.relatedTarget!==g.delegateTarget&&!g.delegateTarget.contains(g.relatedTarget))return m.call(this,g)})(i));const l=hb(e),u=l[a]||(l[a]={}),c=mb(u,i,o?n:null);if(c){c.oneOff=c.oneOff&&s;return}const f=db(i,t.replace(WO,"")),d=o?GO(e,n,i):qO(e,i);d.delegationSelector=o?n:null,d.callable=i,d.oneOff=s,d.uidEvent=f,u[f]=d,e.addEventListener(a,d,o)}function ku(e,t,n,r,s){const o=mb(t[n],r,s);o&&(e.removeEventListener(n,o,!!s),delete t[n][o.uidEvent])}function XO(e,t,n,r){const s=t[n]||{};for(const[o,i]of Object.entries(s))o.includes(r)&&ku(e,t,n,i.callable,i.delegationSelector)}function gb(e){return e=e.replace(zO,""),fb[e]||e}const z={on(e,t,n,r){Bm(e,t,n,r,!1)},one(e,t,n,r){Bm(e,t,n,r,!0)},off(e,t,n,r){if(typeof t!="string"||!e)return;const[s,o,i]=pb(t,n,r),a=i!==t,l=hb(e),u=l[i]||{},c=t.startsWith(".");if(typeof o<"u"){if(!ObLine truncated
`,NULL:"\0"};class Tr{constructor(t){const{command:n,headers:r,body:s,binaryBody:o,escapeHeaderValues:i,skipContentLengthHeader:a}=t;this.command=n,this.headers=Object.assign({},r||{}),o?(this._binaryBody=o,this.isBinaryBody=!0):(this._body=s||"",this.isBinaryBody=!1),this.escapeHeaderValues=i||!1,this.skipContentLengthHeader=a||!1}get body(){return!this._body&&this.isBinaryBody&&(this._body=new TextDecoder().decode(this._binaryBody)),this._body||""}get binaryBody(){return!this._binaryBody&&!this.isBinaryBody&&(this._binaryBody=new TextEncoder().encode(this._body)),this._binaryBody}static fromRawFrame(t,n){const r={},s=o=>o.replace(/^\s+|\s+$/g,"");for(const o of t.headers.reverse()){o.indexOf(":");const i=s(o[0]);let a=s(o[1]);n&&t.command!=="CONNECT"&&t.command!=="CONNECTED"&&(a=Tr.hdrValueUnEscape(a)),r[i]=a}return new Tr({command:t.command,headers:r,binaryBody:t.binaryBody,escapeHeaderValues:n})}toString(){return this.serializeCmdAndHeaders()}serialize(){const t=this.serializeCmdAndHeaders();return this.isBinaryBody?Tr.toUnit8Array(t,this._binaryBody).buffer:t+this._body+No.NULL}serializeCmdAndHeaders(){const t=[this.command];this.skipContentLengthHeader&&delete this.headers["content-length"];for(const n of Object.keys(this.headers||{})){const r=this.headers[n];this.escapeHeaderValues&&this.command!=="CONNECT"&&this.command!=="CONNECTED"?t.push(`${n}:${Tr.hdrValueEscape(`${r}`)}`):t.push(`${n}:${r}`)}return(this.isBinaryBody||!this.isBodyEmpty()&&!this.skipContentLengthHeader)&&t.push(`content-length:${this.bodyLength()}`),t.join(No.LF)+No.LF+No.LF}isBodyEmpty(){return this.bodyLength()===0}bodyLength(){const t=this.binaryBody;return t?t.length:0}static sizeOfUTF8(t){return t?new TextEncoder().encode(t).length:0}static toUnit8Array(t,n){const r=new TextEncoder().encode(t),s=new Uint8Array([0]),o=new Uint8Array(r.length+n.length+s.length);return o.set(r),o.set(n,r.length),o.set(s,r.length+n.length),o}static marshall(t){return new Tr(t).serialize()}static hdrValueEscape(t){return t.replace(/\\/g,"\\\\").replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/:/g,"\\c")}static hdrValueUnEscape(t){return t.replace(/\\r/g,"\r").replace(/\\n/g,`
`).replace(/\\c/g,":").replace(/\\\\/g,"\\")}}const Tp=0,ea=10,ta=13,UP=58;class HP{constructor(t,n){this.onFrame=t,this.onIncomingPing=n,this._encoder=new TextEncoder,this._decoder=new TextDecoder,this._token=[],this._initState()}parseChunk(t,n=!1){let r;if(typeof t=="string"?r=this._encoder.encode(t):r=new Uint8Array(t),n&&r[r.length-1]!==0){const s=new Uint8Array(r.length+1);s.set(r,0),s[r.length]=0,r=s}for(let s=0;s<r.length;s++){const o=r[s];this._onByte(o)}}_collectFrame(t){if(t!==Tp&&t!==ta){if(t===ea){this.onIncomingPing();return}this._onByte=this._collectCommand,this._reinjectByte(t)}}_collectCommand(t){if(t!==ta){if(t===ea){this._results.command=this._consumeTokenAsUTF8(),this._onByte=this._collectHeaders;return}this._consumeByte(t)}}_collectHeaders(t){if(t!==ta){if(t===ea){this._setupCollectBody();return}this._onByte=this._collectHeaderKey,this._reinjectByte(t)}}_reinjectByte(t){this._onByte(t)}_collectHeaderKey(t){if(t===UP){this._headerKey=this._consumeTokenAsUTF8(),this._onByte=this._collectHeaderValue;return}this._consumeByte(t)}_collectHeaderValue(t){if(t!==ta){if(t===ea){this._results.headers.push([this._headerKey,this._consumeTokenAsUTF8()]),this._headerKey=void 0,this._onByte=this._collectHeaders;return}this._consumeByte(t)}}_setupCollectBody(){const t=this._results.headers.filter(n=>n[0]==="content-length")[0];t?(this._bodyBytesRemaining=parseInt(t[1],10),this._onByte=this._collectBodyFixedSize):this._onByte=this._collectBodyNullTerminated}_collectBodyNullTerminated(t){if(t===Tp){this._retrievedBody();return}this._consumeByte(t)}_collectBodyFixedSize(t){if(this._bodyBytesRemaining--===0){this._retrievedBody();return}this._consumeByte(t)}_retrievedBody(){this._results.binaryBody=this._consumeTokenAsRaw();try{this.onFrame(this._results)}catch(t){console.log("Ignoring an exception thrown by a frame handler. Original exception: ",t)}this._initState()}_consumeByte(t){this._token.push(t)}_consumeTokenAsUTF8(){return this._decoder.decode(this._consumeTokenAsRaw())}_consumeTokenAsRaw(){const t=new Uint8Array(this._token);return this._token=[],t}_initState(){this._results={command:void 0,headers:[],binaryBody:void 0},this._token=[],this._headerKey=void 0,this._onByte=this._collectFrame}}var Wn;(function(e){e[e.CONNECTING=0]="CONNECTING",e[e.OPEN=1]="OPEN",e[e.CLOSING=2]="CLOSING",e[e.CLOSED=3]="CLOSED"})(Wn=Wn||(Wn={}));var en;(function(e){e[e.ACTIVE=0]="ACTIVE",e[e.DEACTIVATING=1]="DEACTIVATING",e[e.INACTIVE=2]="INACTIVE"})(en=en||(en={}));class Nt{constructor(t){this.versions=t}supportedVersions(){return this.versions.join(",")}protocolVersions(){return this.versions.map(t=>`v${t.replace(".","")}.stomp`)}}Nt.V1_0="1.0";Nt.V1_1="1.1";Nt.V1_2="1.2";Nt.default=new Nt([Nt.V1_2,Nt.V1_1,Nt.V1_0]);function jP(e,t){e.terminate=function(){const n=()=>{};this.onerror=n,this.onmessage=n,this.onopen=n;const r=new Date,s=Math.random().toString().substring(2,8),o=this.onclose;this.onclose=i=>{const a=new Date().getTime()-r.getTime();t(`Discarded socket (#${s}) closed after ${a}ms, with code/reason: ${i.code}/${i.reason}`)},this.close(),o==null||o.call(e,{code:4001,reason:`Quick discarding socket (#${s}) without waiting for the shutdown sequence.`,wasClean:!1})}}class BP{constructor(t,n,r){this._client=t,this._webSocket=n,this._connected=!1,this._serverFrameHandlers={CONNECTED:s=>{this.debug(`connected to server ${s.headers.server}`),this._connected=!0,this._connectedVersion=s.headers.version,this._connectedVersion===Nt.V1_2&&(this._escapeHeaderValues=!0),this._setupHeartbeat(s.headers),this.onConnect(s)},MESSAGE:s=>{const o=s.headers.subscription,i=this._subscriptions[o]||this.onUnhandledMessage,a=s,l=this,u=this._connectedVersion===Nt.V1_2?a.headers.ack:a.headers["message-id"];a.ack=(c={})=>l.ack(u,o,c),a.nack=(c={})=>l.nack(u,o,c),i(a)},RECEIPT:s=>{const o=this._receiptWatchers[s.headers["receipt-id"]];o?(o(s),delete this._receiptWatchers[s.headers["receipt-id"]]):this.onUnhandledReceipt(s)},ERROR:s=>{this.onStompError(s)}},this._counter=0,this._subscriptions={},this._receiptWatchers={},this._partialData="",this._escapeHeaderValues=!1,this._lastServerActivityTS=Date.now(),this.debug=r.debug,this.stompVersions=r.stompVersions,this.connectHeaders=r.connectHeaders,this.disconnectHeaders=r.disconnectHeaders,this.heartbeatIncoming=r.heartbeatIncoming,this.heartbeatOutgoing=r.heartbeatOutgoing,this.splitLargeFrames=r.splitLargeFrames,this.maxWebSocketChunkSize=r.maxWebSocketChunkSize,this.forceBinaryWSFrames=r.forceBinaryWSFrames,this.logRawCommunication=r.logRawCommunication,this.appendMissingNULLonIncoming=r.appendMissingNULLonIncoming,this.discardWebsocketOnCommFailure=r.discardWebsocketOnCommFailure,this.onConnect=r.onConnect,this.onDisconnect=r.onDisconnect,this.onStompError=r.onStompError,this.onWebSocketClose=r.onWebSocketClose,this.onWebSocketError=r.onWebSocketError,this.onUnhandledMessage=r.onUnhandledMessage,this.onUnhandledReceipt=r.onUnhandledReceipt,this.onUnhandledFrame=r.onUnhandledFrame}get co Line truncated
* Sortable 1.15.2
* @author RubaXa <trash@rubaxa.org>
* @author owenm <owen23355@gmail.com>
* @license MIT
*/function $p(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(s){return Object.getOwnPropertyDescriptor(e,s).enumerable})),n.push.apply(n,r)}return n}function Dn(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?$p(Object(n),!0).forEach(function(r){RR(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):$p(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function ya(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ya=function(t){return typeof t}:ya=function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},ya(e)}function RR(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function nr(){return nr=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},nr.apply(this,arguments)}function DR(e,t){if(e==null)return{};var n={},r=Object.keys(e),s,o;for(o=0;o<r.length;o++)s=r[o],!(t.indexOf(s)>=0)&&(n[s]=e[s]);return n}function MR(e,t){if(e==null)return{};var n=DR(e,t),r,s;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(s=0;s<o.length;s++)r=o[s],!(t.indexOf(r)>=0)&&Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var FR="1.15.2";function Gn(e){if(typeof window<"u"&&window.navigator)return!!navigator.userAgent.match(e)}var lr=Gn(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),xi=Gn(/Edge/i),Lp=Gn(/firefox/i),Wo=Gn(/safari/i)&&!Gn(/chrome/i)&&!Gn(/android/i),ty=Gn(/iP(ad|od|hone)/i),ny=Gn(/chrome/i)&&Gn(/android/i),ry={capture:!1,passive:!1};function Fe(e,t,n){e.addEventListener(t,n,!lr&&ry)}function Le(e,t,n){e.removeEventListener(t,n,!lr&&ry)}function Ka(e,t){if(t){if(t[0]===">"&&(t=t.substring(1)),e)try{if(e.matches)return e.matches(t);if(e.msMatchesSelector)return e.msMatchesSelector(t);if(e.webkitMatchesSelector)return e.webkitMatchesSelector(t)}catch{return!1}return!1}}function VR(e){return e.host&&e!==document&&e.host.nodeType?e.host:e.parentNode}function hn(e,t,n,r){if(e){n=n||document;do{if(t!=null&&(t[0]===">"?e.parentNode===n&&Ka(e,t):Ka(e,t))||r&&e===n)return e;if(e===n)break}while(e=VR(e))}return null}var Pp=/\s+/g;function Bt(e,t,n){if(e&&t)if(e.classList)e.classList[n?"add":"remove"](t);else{var r=(" "+e.className+" ").replace(Pp," ").replace(" "+t+" "," ");e.className=(r+(n?" "+t:"")).replace(Pp," ")}}function ge(e,t,n){var r=e&&e.style;if(r){if(n===void 0)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(e,""):e.currentStyle&&(n=e.currentStyle),t===void 0?n:n[t];!(t in r)&&t.indexOf("webkit")===-1&&(t="-webkit-"+t),r[t]=n+(typeof n=="string"?"":"px")}}function zs(e,t){var n="";if(typeof e=="string")n=e;else do{var r=ge(e,"transform");r&&r!=="none"&&(n=r+" "+n)}while(!t&&(e=e.parentNode));var s=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return s&&new s(n)}function sy(e,t,n){if(e){var r=e.getElementsByTagName(t),s=0,o=r.length;if(n)for(;s<o;s++)n(r[s],s);return r}return[]}function $n(){var e=document.scrollingElement;return e||document.documentElement}function ct(e,t,n,r,s){if(!(!e.getBoundingClientRect&&e!==window)){var o,i,a,l,u,c,f;if(e!==window&&e.parentNode&&e!==$n()?(o=e.getBoundingClientRect(),i=o.top,a=o.left,l=o.bottom,u=o.right,c=o.height,f=o.width):(i=0,a=0,l=window.innerHeight,u=window.innerWidth,c=window.innerHeight,f=window.innerWidth),(t||n)&&e!==window&&(s=s||e.parentNode,!lr))do if(s&&s.getBoundingClientRect&&(ge(s,"transform")!=="none"||n&&ge(s,"position")!=="static")){var d=s.getBoundingClientRect();i-=d.top+parseInt(ge(s,"border-top-width")),a-=d.left+parseInt(ge(s,"border-left-width")),l=i+o.height,u=a+o.width;break}while(s=s.parentNode);if(r&&e!==window){var h=zs(s||e),m=h&&h.a,g=h&&h.d;h&&(i/=g,a/=m,f/=m,c/=g,l=i+c,u=a+f)}return{top:i,left:a,bottom:l,right:u,width:f,height:c}}}function Rp(e,t,n){for(var r=Cr(e,!0),s=ct(e)[t];r;){var o=ct(r)[n],i=void 0;if(i=s>=o,!i)return r;if(r===$n())break;r=Cr(r,!1)}return!1}function ao(e,t,n,r){for(var s=0,o=0,i=e.children;o<i.length;){if(i[o].style.display!=="none"&&i[o]!==_e.ghost&&(r||i[o]!==_e.dragged)&&hn(i[o],n.draggable,e,!1)){if(s===t)return i[o];s++}o++}return null}function id(e,t){for(var n=e.lastElementChild;n&&(n===_e.ghost||ge(n,"display")==="none"||t&&!Ka(n,t));)n=n.previousElementSibling;return n||null}function tn(e,t){var n=0;if(!e||!e.parentNode)return-1;for(;e=e.previousElementSibling;)e.nodeName.toUpperCase()!=="TEMPLATE"&&e!==_e.clone&&(!t||Ka(e,t))&&n++;return n}function Dp(e){var t=0,n=0,r=$n();if(e)do{var s=zs(e),o=s.a,i=s.d;t+=e.scrollLeft*o,n+=e.scrollTop*i}while(e!==r&&(e=e.parentNode));returLine truncated
`,8,S4),[[dt,r.value.categories[s.categoryIndex].description]])])]),p("div",C4,[p("div",O4,[p("h4",x4,j(C(n)("board.boardentry.label",2)),1),r.value.categories[s.categoryIndex].boardEntries.length===0?(B(),G("p",N4,j(C(n)("board.boardentry.label",0)),1)):(B(),it(C(cd),{key:1,modelValue:r.value.categories[s.categoryIndex].boardEntries,"onUpdate:modelValue":g[2]||(g[2]=v=>r.value.categories[s.categoryIndex].boardEntries=v),"item-key":"id",animation:150,"ghost-class":"draggable-ghost",tag:"ul",class:"list-group",handle:".drag-handle"},{default:mn(()=>[(B(!0),G(ke,null,Kt(r.value.categories[s.categoryIndex].boardEntries,(v,y)=>(B(),G("li",{key:v.id,class:"list-group-item bg-body-secondary p-0"},[p("div",k4,[p("div",I4,[p("div",$4,[re(C(Se),{icon:["fas","grip-lines"],class:"px-2"})]),et(p("input",{type:"text",id:`category-name-${y}`,"onUpdate:modelValue":S=>v.name=S,class:"form-control rounded-0 h-100"},null,8,L4),[[dt,v.name]])]),p("div",P4,[p("button",{class:"btn btn-primary rounded-0",onClick:S=>d(y)},[re(C(Se),{icon:["fas","edit"],size:"sm"})],8,R4),p("div",D4,[p("button",{class:"btn btn-primary rounded-0 py-0 lh-sm",onClick:S=>c(y),disabled:y===0},[re(C(Se),{icon:["fas","angle-up"],size:"xs"})],8,M4),p("button",{class:"btn btn-primary rounded-0 py-0 lh-sm",onClick:S=>f(y),disabled:y===r.value.categories[s.categoryIndex].boardEntries.length-1},[re(C(Se),{icon:["fas","angle-down"],size:"xs"})],8,F4)]),p("button",{class:It(["btn btn-danger rounded-start-0 rounded-0",[{"rounded-bottom-end":y===r.value.categories[s.categoryIndex].boardEntries.length-1},{"rounded-top-end":y===0}]]),onClick:S=>u(y)},[re(C(Se),{icon:["fas","trash"],size:"sm"})],10,V4)])])]))),128))]),_:1},8,["modelValue"])),p("label",U4,j(C(n)("board.boardentry.add")),1),p("div",H4,[et(p("input",{type:"text",id:"new-category-name",class:"form-control","onUpdate:modelValue":g[3]||(g[3]=v=>a.value=v),placeholder:C(n)("board.boardentry.name"),onKeyup:ls(l,["enter"])},null,40,j4),[[dt,a.value]]),p("button",{class:"btn btn-primary",onClick:l},[re(C(Se),{icon:["fas","plus"]})])])])])])]))}}),W4=Mn(B4,[["__scopeId","data-v-c5bb5ee8"]]),z4={class:"d-flex flex-column h-100"},Y4={class:"flex-grow-1 p-2"},K4={class:"row"},q4={class:"col"},G4={class:"border-bottom border-3 border-primary"},X4={for:"board-name"},Q4=["placeholder"],J4={class:"form-check mt-2"},Z4={for:"points-for-title",class:"form-check-label"},eD={class:"row mt-3"},tD={class:"col"},nD={class:"d-flex justify-content-between w-100"},rD={class:"flex-grow-1 d-flex align-items-center g-3 justify-content-start"},sD={class:"drag-handle h-100 d-flex justify-content-center align-items-center cursor-move border-end border-1 bg-primary bg-opacity-10"},oD=["id","onUpdate:modelValue"],iD={class:"d-flex"},aD=["onClick"],lD={class:"d-flex flex-column justify-content-center align-items-center h-100",role:"group","aria-label":"Vertical button group"},cD=["onClick","disabled"],uD=["onClick","disabled"],fD=["onClick"],dD={class:"mt-2",for:"new-category-name"},hD={class:"input-group mb-3"},mD=["placeholder"],pD=Re({__name:"EditBoardPanel",props:{modelValue:{required:!0},modelModifiers:{}},emits:Qn(["editCategory"],["update:modelValue"]),setup(e,{emit:t}){const{t:n}=ot(),r=t,s=pi(e,"modelValue"),o=te("");function i(){if(s.value.categories.length>=12)return;const f=new Du(o.value,"");s.value.categories.push(f)}function a(f){s.value.categories.splice(f,1)}function l(f){if(f===0||s.value.categories.length<=1)return;const d=s.value.categories[f];s.value.categories[f]=s.value.categories[f-1],s.value.categories[f-1]=d}function u(f){if(f===s.value.categories.length-1||s.value.categories.length<=1)return;const d=s.value.categories[f];s.value.categories[f]=s.value.categories[f+1],s.value.categories[f+1]=d}function c(f){r("editCategory",f)}return(f,d)=>(B(),G("div",z4,[p("div",Y4,[p("div",K4,[p("div",q4,[p("h2",G4,j(C(n)("board.infos")),1),p("label",X4,j(C(n)("board.name")),1),et(p("input",{type:"text",id:"board-name",class:"form-control","onUpdate:modelValue":d[0]||(d[0]=h=>s.value.boardName=h),placeholder:C(n)("board.name")},null,8,Q4),[[dt,s.value.boardName]]),p("div",J4,[et(p("input",{class:"form-check-input",type:"checkbox",id:"points-for-title","onUpdate:modelValue":d[1]||(d[1]=h=>s.value.pointsAreTitle=h)},null,512),[[P0,s.value.pointsAreTitle]]),p("label",Z4,j(C(n)("board.options.pointsForTitle")),1)])])]),p("div",eD,[p("div",tD,[p("h4",null,j(C(n)("board.category.label",2)),1),s.value.categories.length===0?(B(),G(ke,{key:0},[Ne(j(C(n)("board.category.label",0)),1)],64)):(B(),it(C(cd),{key:1,modelValue:s.value.categories,"onUpdate:modelValue":d[2]||(d[2]=h=>s.value.categories=h),"item-key":"id",animation:150,"ghost-class":"draggable-ghost",tag:"ul",class:"list-group",handle:".drag-handle"},{default:mn(()=>[(B(!0),G(ke,null,Kt(s.value.categories,(h,m)=>(B(),G("li",{key:h.id,class:"list-group-item bg-body-secondary p-0"},[p("div",nD,[p("div",rD,[p("div",sD,[re(C(Se),{icon:["fas","grip-lines"],class:"px-2"}) Line truncated
@@ -1,813 +0,0 @@
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(s){if(s.ep)return;s.ep=!0;const i=n(s);fetch(s.href,i)}})();/**
* @vue/shared v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**//*! #__NO_SIDE_EFFECTS__ */function jl(e,t){const n=new Set(e.split(","));return r=>n.has(r)}const ke={},Mr=[],Ct=()=>{},p_=()=>!1,go=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ul=e=>e.startsWith("onUpdate:"),Ze=Object.assign,Hl=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},g_=Object.prototype.hasOwnProperty,we=(e,t)=>g_.call(e,t),ce=Array.isArray,Fr=e=>_o(e)==="[object Map]",hm=e=>_o(e)==="[object Set]",he=e=>typeof e=="function",Ge=e=>typeof e=="string",br=e=>typeof e=="symbol",Fe=e=>e!==null&&typeof e=="object",pm=e=>(Fe(e)||he(e))&&he(e.then)&&he(e.catch),gm=Object.prototype.toString,_o=e=>gm.call(e),__=e=>_o(e).slice(8,-1),_m=e=>_o(e)==="[object Object]",Vl=e=>Ge(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Es=jl(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),vo=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},v_=/-(\w)/g,Xt=vo(e=>e.replace(v_,(t,n)=>n?n.toUpperCase():"")),b_=/\B([A-Z])/g,rs=vo(e=>e.replace(b_,"-$1").toLowerCase()),bo=vo(e=>e.charAt(0).toUpperCase()+e.slice(1)),Zo=vo(e=>e?`on${bo(e)}`:""),Rn=(e,t)=>!Object.is(e,t),Di=(e,...t)=>{for(let n=0;n<e.length;n++)e[n](...t)},vm=(e,t,n,r=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},ja=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let nu;const bm=()=>nu||(nu=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Zn(e){if(ce(e)){const t={};for(let n=0;n<e.length;n++){const r=e[n],s=Ge(r)?A_(r):Zn(r);if(s)for(const i in s)t[i]=s[i]}return t}else if(Ge(e)||Fe(e))return e}const y_=/;(?![^(]*\))/g,E_=/:([^]+)/,w_=/\/\*[^]*?\*\//g;function A_(e){const t={};return e.replace(w_,"").split(y_).forEach(n=>{if(n){const r=n.split(E_);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Nt(e){let t="";if(Ge(e))t=e;else if(ce(e))for(let n=0;n<e.length;n++){const r=Nt(e[n]);r&&(t+=r+" ")}else if(Fe(e))for(const n in e)e[n]&&(t+=n+" ");return t.trim()}const T_="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",O_=jl(T_);function ym(e){return!!e||e===""}const ue=e=>Ge(e)?e:e==null?"":ce(e)||Fe(e)&&(e.toString===gm||!he(e.toString))?JSON.stringify(e,Em,2):String(e),Em=(e,t)=>t&&t.__v_isRef?Em(e,t.value):Fr(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],i)=>(n[ea(r,i)+" =>"]=s,n),{})}:hm(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>ea(n))}:br(t)?ea(t):Fe(t)&&!ce(t)&&!_m(t)?String(t):t,ea=(e,t="")=>{var n;return br(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/**
* @vue/reactivity v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/let yt;class wm{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=yt,!t&&yt&&(this.index=(yt.scopes||(yt.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=yt;try{return yt=this,t()}finally{yt=n}}}on(){yt=this}off(){yt=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n<r;n++)this.effects[n].stop();for(n=0,r=this.cleanups.length;n<r;n++)this.cleanups[n]();if(this.scopes)for(n=0,r=this.scopes.length;n<r;n++)this.scopes[n].stop(!0);if(!this.detached&&this.parent&&!t){const s=this.parent.scopes.pop();s&&s!==this&&(this.parent.scopes[this.index]=s,s.index=this.index)}this.parent=void 0,this._active=!1}}}function Bl(e){return new wm(e)}function S_(e,t=yt){t&&t.active&&t.effects.push(e)}function Am(){return yt}function C_(e){yt&&yt.cleanups.push(e)}let ar;class Wl{constructor(t,n,r,s){this.fn=t,this.trigger=n,this.scheduler=r,this.active=!0,this.deps=[],this._dirtyLevel=5,this._trackId=0,this._runnings=0,this._shouldSchedule=!1,this._depsLength=0,S_(this,s)}get dirty(){if(this._dirtyLevel===2)return!1;if(this._dirtyLevel===3||this._dirtyLevel===4){this._dirtyLevel=1,Un();for(let t=0;t<this._depsLength;t++){const n=this.deps[t];if(n.computed){if(n.computed.effect._dirtyLevel===2)return!0;if(N_(n.computed),this._dirtyLevel>=5)break}}this._dirtyLevel===1&&(this._dirtyLevel=0),Hn()}return this._dirtyLevel>=5}set dirty(t){this._dirtyLevel=t?5:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Ln,n=ar;try{return Ln=!0,ar=this,this._runnings++,ru(this),this.fn()}finally{su(this),this._runnings--,ar=n,Ln=t}}stop(){this.active&&(ru(this),su(this),this.onStop&&this.onStop(),this.active=!1)}}function N_(e){return e.value}function ru(e){e._trackId++,e._depsLength=0}function su(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t<e.deps.length;t++)Tm(e.deps[t],e);e.deps.length=e._depsLength}}function Tm(e,t){const n=e.get(t);n!==void 0&&t._trackId!==n&&(e.delete(t),e.size===0&&e.cleanup())}let Ln=!0,Ua=0;const Om=[];function Un(){Om.push(Ln),Ln=!1}function Hn(){const e=Om.pop();Ln=e===void 0?!0:e}function Yl(){Ua++}function Kl(){for(Ua--;!Ua&&Ha.length;)Ha.shift()()}function Sm(e,t,n){if(t.get(e)!==e._trackId){t.set(e,e._trackId);const r=e.deps[e._depsLength];r!==t?(r&&Tm(r,e),e.deps[e._depsLength++]=t):e._depsLength++}}const Ha=[];function Cm(e,t,n){Yl();for(const r of e.keys()){if(!e.computed&&r.computed&&e.get(r)===r._trackId&&r._runnings>0){r._dirtyLevel=2;continue}let s;r._dirtyLevel<t&&(s??(s=e.get(r)===r._trackId))&&(r._shouldSchedule||(r._shouldSchedule=r._dirtyLevel===0),r.computed&&r._dirtyLevel===2&&(r._shouldSchedule=!0),r._dirtyLevel=t),r._shouldSchedule&&(s??(s=e.get(r)===r._trackId))&&(r.trigger(),(!r._runnings||r.allowRecurse)&&r._dirtyLevel!==3&&(r._shouldSchedule=!1,r.scheduler&&Ha.push(r.scheduler)))}Kl()}const Nm=(e,t)=>{const n=new Map;return n.cleanup=e,n.computed=t,n},Xi=new WeakMap,lr=Symbol(""),Va=Symbol("");function _t(e,t,n){if(Ln&&ar){let r=Xi.get(e);r||Xi.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=Nm(()=>r.delete(n))),Sm(ar,s)}}function on(e,t,n,r,s,i){const o=Xi.get(e);if(!o)return;let a=[];if(t==="clear")a=[...o.values()];else if(n==="length"&&ce(e)){const l=Number(r);o.forEach((u,c)=>{(c==="length"||!br(c)&&c>=l)&&a.push(u)})}else switch(n!==void 0&&a.push(o.get(n)),t){case"add":ce(e)?Vl(n)&&a.push(o.get("length")):(a.push(o.get(lr)),Fr(e)&&a.push(o.get(Va)));break;case"delete":ce(e)||(a.push(o.get(lr)),Fr(e)&&a.push(o.get(Va)));break;case"set":Fr(e)&&a.push(o.get(lr));break}Yl();for(const l of a)l&&Cm(l,5);Kl()}function L_(e,t){const n=Xi.get(e);return n&&n.get(t)}const I_=jl("__proto__,__v_isRef,__isVue"),Lm=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(br)),iu=P_();function P_(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=Ae(this);for(let i=0,o=this.length;i<o;i++)_t(r,"get",i+"");const s=r[t](...n);return s===-1||s===!1?r[t](...n.map(Ae)):s}}),["push","pop","shift","unshift","splice"].forEach(t=>{e[t]=function(...n){Un(),Yl();const r=Ae(this)[t].apply(this,n);return Kl(),Hn(),r}}),e}function R_(e){br(e)||(e=String(e));const t=Ae(this);return _t(t,"has",e),t.hasOwnProperty(e)}class Im{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){const s=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return i;if(n==="__v_raw")return r===(s?i?Y_:km:i?xm:Rm).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const o=ce(t);if(!s){if(o&&we(iu,n))return Reflect.get(iu,n,r);if(n==="hasOwnProperty")return R_}const a=Reflect.get(t,n,r);return(br(n)?Lm.has(n):I_(n))||(s||_t(t,"get",n),i)?a:He(a)?o&&Vl(n)?a:a.value:Fe(a)?s?Dm(a):Vn(a):a}}class Pm extends Im{constructor(t=!1){super(!1,t)}set(t,n,r,s){let i=t[n];if(!this._isShallow){const l=Vr(i);if(!Ji(rLine truncated
* @vue/runtime-core v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/function Pn(e,t,n,r){try{return r?e(...r):e()}catch(s){Eo(s,t,n)}}function Mt(e,t,n,r){if(he(e)){const s=Pn(e,t,n,r);return s&&pm(s)&&s.catch(i=>{Eo(i,t,n)}),s}if(ce(e)){const s=[];for(let i=0;i<e.length;i++)s.push(Mt(e[i],t,n,r));return s}}function Eo(e,t,n,r=!0){const s=t?t.vnode:null;if(t){let i=t.parent;const o=t.proxy,a=`https://vuejs.org/error-reference/#runtime-${n}`;for(;i;){const u=i.ec;if(u){for(let c=0;c<u.length;c++)if(u[c](e,o,a)===!1)return}i=i.parent}const l=t.appContext.config.errorHandler;if(l){Un(),Pn(l,null,10,[e,o,a]),Hn();return}}ev(e,n,s,r)}function ev(e,t,n,r=!0){console.error(e)}let Ds=!1,Ba=!1;const st=[];let Yt=0;const jr=[];let An=null,Qn=0;const Vm=Promise.resolve();let Zl=null;function Ms(e){const t=Zl||Vm;return e?t.then(this?e.bind(this):e):t}function tv(e){let t=Yt+1,n=st.length;for(;t<n;){const r=t+n>>>1,s=st[r],i=Fs(s);i<e||i===e&&s.pre?t=r+1:n=r}return t}function ec(e){(!st.length||!st.includes(e,Ds&&e.allowRecurse?Yt+1:Yt))&&(e.id==null?st.push(e):st.splice(tv(e.id),0,e),Bm())}function Bm(){!Ds&&!Ba&&(Ba=!0,Zl=Vm.then(Ym))}function nv(e){const t=st.indexOf(e);t>Yt&&st.splice(t,1)}function rv(e){ce(e)?jr.push(...e):(!An||!An.includes(e,e.allowRecurse?Qn+1:Qn))&&jr.push(e),Bm()}function uu(e,t,n=Ds?Yt+1:0){for(;n<st.length;n++){const r=st[n];if(r&&r.pre){if(e&&r.id!==e.uid)continue;st.splice(n,1),n--,r()}}}function Wm(e){if(jr.length){const t=[...new Set(jr)].sort((n,r)=>Fs(n)-Fs(r));if(jr.length=0,An){An.push(...t);return}for(An=t,Qn=0;Qn<An.length;Qn++){const n=An[Qn];n.active!==!1&&n()}An=null,Qn=0}}const Fs=e=>e.id==null?1/0:e.id,sv=(e,t)=>{const n=Fs(e)-Fs(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Ym(e){Ba=!1,Ds=!0,st.sort(sv);try{for(Yt=0;Yt<st.length;Yt++){const t=st[Yt];t&&t.active!==!1&&Pn(t,null,14)}}finally{Yt=0,st.length=0,Wm(),Ds=!1,Zl=null,(st.length||jr.length)&&Ym()}}function iv(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||ke;let s=n;const i=t.startsWith("update:"),o=i&&t.slice(7);if(o&&o in r){const c=`${o==="modelValue"?"model":o}Modifiers`,{number:f,trim:d}=r[c]||ke;d&&(s=n.map(m=>Ge(m)?m.trim():m)),f&&(s=n.map(ja))}let a,l=r[a=Zo(t)]||r[a=Zo(Xt(t))];!l&&i&&(l=r[a=Zo(rs(t))]),l&&Mt(l,e,6,s);const u=r[a+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,Mt(u,e,6,s)}}function Km(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const i=e.emits;let o={},a=!1;if(!he(e)){const l=u=>{const c=Km(u,t,!0);c&&(a=!0,Ze(o,c))};!n&&t.mixins.length&&t.mixins.forEach(l),e.extends&&l(e.extends),e.mixins&&e.mixins.forEach(l)}return!i&&!a?(Fe(e)&&r.set(e,null),null):(ce(i)?i.forEach(l=>o[l]=null):Ze(o,i),Fe(e)&&r.set(e,o),o)}function wo(e,t){return!e||!go(t)?!1:(t=t.slice(2).replace(/Once$/,""),we(e,t[0].toLowerCase()+t.slice(1))||we(e,rs(t))||we(e,t))}let ct=null,Ao=null;function Qi(e){const t=ct;return ct=e,Ao=e&&e.type.__scopeId||null,t}function ov(e){Ao=e}function av(){Ao=null}function er(e,t=ct,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&wu(-1);const i=Qi(t);let o;try{o=e(...s)}finally{Qi(i),r._d&&wu(1)}return o};return r._n=!0,r._c=!0,r._d=!0,r}function ta(e){const{type:t,vnode:n,proxy:r,withProxy:s,propsOptions:[i],slots:o,attrs:a,emit:l,render:u,renderCache:c,props:f,data:d,setupState:m,ctx:h,inheritAttrs:y}=e,v=Qi(e);let w,O;try{if(n.shapeFlag&4){const A=s||r,C=A;w=Wt(u.call(C,A,c,f,m,d,h)),O=a}else{const A=t;w=Wt(A.length>1?A(f,{attrs:a,slots:o,emit:l}):A(f,null)),O=t.props?a:lv(a)}}catch(A){Ts.length=0,Eo(A,e,1),w=ye(dr)}let E=w;if(O&&y!==!1){const A=Object.keys(O),{shapeFlag:C}=E;A.length&&C&7&&(i&&A.some(Ul)&&(O=cv(O,i)),E=Br(E,O,!1,!0))}return n.dirs&&(E=Br(E,null,!1,!0),E.dirs=E.dirs?E.dirs.concat(n.dirs):n.dirs),n.transition&&(E.transition=n.transition),w=E,Qi(v),w}const lv=e=>{let t;for(const n in e)(n==="class"||n==="style"||go(n))&&((t||(t={}))[n]=e[n]);return t},cv=(e,t)=>{const n={};for(const r in e)(!Ul(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function uv(e,t,n){const{props:r,children:s,component:i}=e,{props:o,children:a,patchFlag:l}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&l>=0){if(l&1024)return!0;if(l&16)return r?fu(r,o,u):!!o;if(l&8){const c=t.dynamicProps;for(let f=0;f<c.length;f++){const d=c[f];if(o[d]!==r[d]&&!wo(u,d))return!0}}}else return(s||a)&&(!a||!a.$stable)?!0:r===o?!1:r?o?fu(r,o,u):!0:!!o;return!1}function fu(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let s=0;s<r.length;s++){const i=r[s];if(t[i]!==e[i]&&!wo(n,i))return!0}return!1}function fv({vnode:e,parent:t},n){for(;t;){const r=t.subTree;if(r.suspense&&r.suspense.activeBranch===e&&(r.el=e.el),r===e)(e=t.vnode).el=n,t=t.parent;else break}}const dv="components";function tc(e,t){return hv(dv,e,!0,t)||e}const mv=Symbol.for("v-ndc");function hv(e,t,n=!0,r=!1){const s=ct||Je;if(s){const i=s.type;{const a=ib(i,!1);if(a&&(a===t||a===Xt(t)||a===bo(Xt(t))))return i}const o=du(s[e]||i[e],t)||du(s.appContext[e],t);return!o&&r?i:o}}f Line truncated
* @vue/runtime-dom v3.4.29
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/const lb="http://www.w3.org/2000/svg",cb="http://www.w3.org/1998/Math/MathML",nn=typeof document<"u"?document:null,Su=nn&&nn.createElement("template"),ub={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?nn.createElementNS(lb,e):t==="mathml"?nn.createElementNS(cb,e):n?nn.createElement(e,{is:n}):nn.createElement(e);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>nn.createTextNode(e),createComment:e=>nn.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>nn.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,i){const o=n?n.previousSibling:t.lastChild;if(s&&(s===i||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===i||!(s=s.nextSibling)););else{Su.innerHTML=r==="svg"?`<svg>${e}</svg>`:r==="mathml"?`<math>${e}</math>`:e;const a=Su.content;if(r==="svg"||r==="mathml"){const l=a.firstChild;for(;l.firstChild;)a.appendChild(l.firstChild);a.removeChild(l)}t.insertBefore(a,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},fb=Symbol("_vtc");function db(e,t,n){const r=e[fb];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Cu=Symbol("_vod"),mb=Symbol("_vsh"),hb=Symbol(""),pb=/(^|;)\s*display\s*:/;function gb(e,t,n){const r=e.style,s=Ge(n);let i=!1;if(n&&!s){if(t)if(Ge(t))for(const o of t.split(";")){const a=o.slice(0,o.indexOf(":")).trim();n[a]==null&&Ui(r,a,"")}else for(const o in t)n[o]==null&&Ui(r,o,"");for(const o in n)o==="display"&&(i=!0),Ui(r,o,n[o])}else if(s){if(t!==n){const o=r[hb];o&&(n+=";"+o),r.cssText=n,i=pb.test(n)}}else t&&e.removeAttribute("style");Cu in e&&(e[Cu]=i?r.display:"",e[mb]&&(r.display="none"))}const Nu=/\s*!important$/;function Ui(e,t,n){if(ce(n))n.forEach(r=>Ui(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=_b(e,t);Nu.test(n)?e.setProperty(rs(r),n.replace(Nu,""),"important"):e[r]=n}}const Lu=["Webkit","Moz","ms"],ia={};function _b(e,t){const n=ia[t];if(n)return n;let r=Xt(t);if(r!=="filter"&&r in e)return ia[t]=r;r=bo(r);for(let s=0;s<Lu.length;s++){const i=Lu[s]+r;if(i in e)return ia[t]=i}return t}const Iu="http://www.w3.org/1999/xlink";function Pu(e,t,n,r,s,i=O_(t)){r&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(Iu,t.slice(6,t.length)):e.setAttributeNS(Iu,t,n):n==null||i&&!ym(n)?e.removeAttribute(t):e.setAttribute(t,i?"":String(n))}function vb(e,t,n,r,s,i,o){if(t==="innerHTML"||t==="textContent"){r&&o(r,s,i),e[t]=n??"";return}const a=e.tagName;if(t==="value"&&a!=="PROGRESS"&&!a.includes("-")){const u=a==="OPTION"?e.getAttribute("value")||"":e.value,c=n==null?"":String(n);(u!==c||!("_value"in e))&&(e.value=c),n==null&&e.removeAttribute(t),e._value=n;return}let l=!1;if(n===""||n==null){const u=typeof e[t];u==="boolean"?n=ym(n):n==null&&u==="string"?(n="",l=!0):u==="number"&&(n=0,l=!0)}try{e[t]=n}catch{}l&&e.removeAttribute(t)}function Cr(e,t,n,r){e.addEventListener(t,n,r)}function bb(e,t,n,r){e.removeEventListener(t,n,r)}const Ru=Symbol("_vei");function yb(e,t,n,r,s=null){const i=e[Ru]||(e[Ru]={}),o=i[t];if(r&&o)o.value=r;else{const[a,l]=Eb(t);if(r){const u=i[t]=Tb(r,s);Cr(e,a,u,l)}else o&&(bb(e,a,o,l),i[t]=void 0)}}const xu=/(?:Once|Passive|Capture)$/;function Eb(e){let t;if(xu.test(e)){t={};let r;for(;r=e.match(xu);)e=e.slice(0,e.length-r[0].length),t[r[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):rs(e.slice(2)),t]}let oa=0;const wb=Promise.resolve(),Ab=()=>oa||(wb.then(()=>oa=0),oa=Date.now());function Tb(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Mt(Ob(r,n.value),t,5,[r])};return n.value=e,n.attached=Ab(),n}function Ob(e,t){if(ce(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const ku=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Sb=(e,t,n,r,s,i,o,a,l)=>{const u=s==="svg";t==="class"?db(e,r,u):t==="style"?gb(e,n,r):go(t)?Ul(t)||yb(e,t,n,r,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Cb(e,t,r,u))?(vb(e,t,r,i,o,a,l),(t==="value"||t==="checked"||t==="selected")&&Pu(e,t,r,u,o,t!=="value")):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Pu(e,t,r,u))};function Cb(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&ku(t)&&he(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return ku(t)&&Ge(n)?!1:t in e}const $u=e=>{const t=e.props["onUpdate:modelValue"]||!1;return ce(t)?n=>Di(t,n):t};function Nb(e){e.target.composing=!0}fun Line truncated
* pinia v2.1.7
* (c) 2023 Eduardo San Martin Morote
* @license MIT
*/let gh;const No=e=>gh=e,_h=Symbol();function Ja(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var Ss;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(Ss||(Ss={}));function $b(){const e=Bl(!0),t=e.run(()=>ge({}));let n=[],r=[];const s=Xl({install(i){No(s),s._a=i,i.provide(_h,s),i.config.globalProperties.$pinia=s,r.forEach(o=>n.push(o)),r=[]},use(i){return!this._a&&!kb?r.push(i):n.push(i),this},_p:n,_a:null,_e:e,_s:new Map,state:t});return s}const vh=()=>{};function Fu(e,t,n,r=vh){e.push(t);const s=()=>{const i=e.indexOf(t);i>-1&&(e.splice(i,1),r())};return!n&&Am()&&C_(s),s}function Tr(e,...t){e.slice().forEach(n=>{n(...t)})}const Db=e=>e();function Qa(e,t){e instanceof Map&&t instanceof Map&&t.forEach((n,r)=>e.set(r,n)),e instanceof Set&&t instanceof Set&&t.forEach(e.add,e);for(const n in t){if(!t.hasOwnProperty(n))continue;const r=t[n],s=e[n];Ja(s)&&Ja(r)&&e.hasOwnProperty(n)&&!He(r)&&!In(r)?e[n]=Qa(s,r):e[n]=r}return e}const Mb=Symbol();function Fb(e){return!Ja(e)||!e.hasOwnProperty(Mb)}const{assign:wn}=Object;function jb(e){return!!(He(e)&&e.effect)}function Ub(e,t,n,r){const{state:s,actions:i,getters:o}=t,a=n.state.value[e];let l;function u(){a||(n.state.value[e]=s?s():{});const c=J_(n.state.value[e]);return wn(c,i,Object.keys(o||{}).reduce((f,d)=>(f[d]=Xl(ne(()=>{No(n);const m=n._s.get(e);return o[d].call(m,m)})),f),{}))}return l=bh(e,u,t,n,r,!0),l}function bh(e,t,n={},r,s,i){let o;const a=wn({actions:{}},n),l={deep:!0};let u,c,f=[],d=[],m;const h=r.state.value[e];!i&&!h&&(r.state.value[e]={}),ge({});let y;function v($){let P;u=c=!1,typeof $=="function"?($(r.state.value[e]),P={type:Ss.patchFunction,storeId:e,events:m}):(Qa(r.state.value[e],$),P={type:Ss.patchObject,payload:$,storeId:e,events:m});const q=y=Symbol();Ms().then(()=>{y===q&&(u=!0)}),c=!0,Tr(f,P,r.state.value[e])}const w=i?function(){const{state:P}=n,q=P?P():{};this.$patch(ie=>{wn(ie,q)})}:vh;function O(){o.stop(),f=[],d=[],r._s.delete(e)}function E($,P){return function(){No(r);const q=Array.from(arguments),ie=[],Q=[];function le(ee){ie.push(ee)}function je(ee){Q.push(ee)}Tr(d,{args:q,name:$,store:C,after:le,onError:je});let Ce;try{Ce=P.apply(this&&this.$id===e?this:C,q)}catch(ee){throw Tr(Q,ee),ee}return Ce instanceof Promise?Ce.then(ee=>(Tr(ie,ee),ee)).catch(ee=>(Tr(Q,ee),Promise.reject(ee))):(Tr(ie,Ce),Ce)}}const A={_p:r,$id:e,$onAction:Fu.bind(null,d),$patch:v,$reset:w,$subscribe($,P={}){const q=Fu(f,$,P.detached,()=>ie()),ie=o.run(()=>it(()=>r.state.value[e],Q=>{(P.flush==="sync"?c:u)&&$({storeId:e,type:Ss.direct,events:m},Q)},wn({},l,P)));return q},$dispose:O},C=Vn(A);r._s.set(e,C);const I=(r._a&&r._a.runWithContext||Db)(()=>r._e.run(()=>(o=Bl()).run(t)));for(const $ in I){const P=I[$];if(He(P)&&!jb(P)||In(P))i||(h&&Fb(P)&&(He(P)?P.value=h[$]:Qa(P,h[$])),r.state.value[e][$]=P);else if(typeof P=="function"){const q=E($,P);I[$]=q,a.actions[$]=P}}return wn(C,I),wn(Ae(C),I),Object.defineProperty(C,"$state",{get:()=>r.state.value[e],set:$=>{v(P=>{wn(P,$)})}}),r._p.forEach($=>{wn(C,o.run(()=>$({store:C,app:r._a,pinia:r,options:a})))}),h&&i&&n.hydrate&&n.hydrate(C.$state,h),u=!0,c=!0,C}function Hb(e,t,n){let r,s;const i=typeof t=="function";r=e,s=i?n:t;function o(a,l){const u=Pv();return a=a||(u?tt(_h,null):null),a&&No(a),a=gh,a._s.has(r)||(i?bh(r,t,s,a):Ub(r,s,a)),a._s.get(r)}return o.$id=r,o}/*!
* shared v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/const to=typeof window<"u",Bn=(e,t=!1)=>t?Symbol.for(e):Symbol(e),Vb=(e,t,n)=>Bb({l:e,k:t,s:n}),Bb=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),Ke=e=>typeof e=="number"&&isFinite(e),Wb=e=>Eh(e)==="[object Date]",xn=e=>Eh(e)==="[object RegExp]",Lo=e=>fe(e)&&Object.keys(e).length===0,nt=Object.assign;let ju;const rn=()=>ju||(ju=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Uu(e){return e.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}const Yb=Object.prototype.hasOwnProperty;function no(e,t){return Yb.call(e,t)}const De=Array.isArray,Re=e=>typeof e=="function",G=e=>typeof e=="string",ve=e=>typeof e=="boolean",Se=e=>e!==null&&typeof e=="object",Kb=e=>Se(e)&&Re(e.then)&&Re(e.catch),yh=Object.prototype.toString,Eh=e=>yh.call(e),fe=e=>{if(!Se(e))return!1;const t=Object.getPrototypeOf(e);return t===null||t.constructor===Object},zb=e=>e==null?"":De(e)||fe(e)&&e.toString===yh?JSON.stringify(e,null,2):String(e);function Gb(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}function Io(e){let t=e;return()=>++t}function qb(e,t){typeof console<"u"&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const bi=e=>!Se(e)||De(e);function Hi(e,t){if(bi(e)||bi(t))throw new Error("Invalid value");const n=[{src:e,des:t}];for(;n.length;){const{src:r,des:s}=n.pop();Object.keys(r).forEach(i=>{bi(r[i])||bi(s[i])?s[i]=r[i]:n.push({src:r[i],des:s[i]})})}}/*!
* message-compiler v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/function Xb(e,t,n){return{line:e,column:t,offset:n}}function ro(e,t,n){return{start:e,end:t}}const Jb=/\{([0-9a-zA-Z]+)\}/g;function wh(e,...t){return t.length===1&&Qb(t[0])&&(t=t[0]),(!t||!t.hasOwnProperty)&&(t={}),e.replace(Jb,(n,r)=>t.hasOwnProperty(r)?t[r]:"")}const Ah=Object.assign,Hu=e=>typeof e=="string",Qb=e=>e!==null&&typeof e=="object";function Th(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}const ac={USE_MODULO_SYNTAX:1,__EXTEND_POINT__:2},Zb={[ac.USE_MODULO_SYNTAX]:"Use modulo before '{{0}}'."};function ey(e,t,...n){const r=wh(Zb[e],...n||[]),s={message:String(r),code:e};return t&&(s.location=t),s}const oe={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16,__EXTEND_POINT__:17},ty={[oe.EXPECTED_TOKEN]:"Expected token: '{0}'",[oe.INVALID_TOKEN_IN_PLACEHOLDER]:"Invalid token in placeholder: '{0}'",[oe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]:"Unterminated single quote in placeholder",[oe.UNKNOWN_ESCAPE_SEQUENCE]:"Unknown escape sequence: \\{0}",[oe.INVALID_UNICODE_ESCAPE_SEQUENCE]:"Invalid unicode escape sequence: {0}",[oe.UNBALANCED_CLOSING_BRACE]:"Unbalanced closing brace",[oe.UNTERMINATED_CLOSING_BRACE]:"Unterminated closing brace",[oe.EMPTY_PLACEHOLDER]:"Empty placeholder",[oe.NOT_ALLOW_NEST_PLACEHOLDER]:"Not allowed nest placeholder",[oe.INVALID_LINKED_FORMAT]:"Invalid linked format",[oe.MUST_HAVE_MESSAGES_IN_PLURAL]:"Plural must have messages",[oe.UNEXPECTED_EMPTY_LINKED_MODIFIER]:"Unexpected empty linked modifier",[oe.UNEXPECTED_EMPTY_LINKED_KEY]:"Unexpected empty linked key",[oe.UNEXPECTED_LEXICAL_ANALYSIS]:"Unexpected lexical analysis in token: '{0}'",[oe.UNHANDLED_CODEGEN_NODE_TYPE]:"unhandled codegen node type: '{0}'",[oe.UNHANDLED_MINIFIER_NODE_TYPE]:"unhandled mimifier node type: '{0}'"};function is(e,t,n={}){const{domain:r,messages:s,args:i}=n,o=wh((s||ty)[e]||"",...i||[]),a=new SyntaxError(String(o));return a.code=e,t&&(a.location=t),a.domain=r,a}function ny(e){throw e}const Zt=" ",ry="\r",at=`
`,sy="\u2028",iy="\u2029";function oy(e){const t=e;let n=0,r=1,s=1,i=0;const o=I=>t[I]===ry&&t[I+1]===at,a=I=>t[I]===at,l=I=>t[I]===iy,u=I=>t[I]===sy,c=I=>o(I)||a(I)||l(I)||u(I),f=()=>n,d=()=>r,m=()=>s,h=()=>i,y=I=>o(I)||l(I)||u(I)?at:t[I],v=()=>y(n),w=()=>y(n+i);function O(){return i=0,c(n)&&(r++,s=0),o(n)&&n++,n++,s++,t[n]}function E(){return o(n+i)&&i++,i++,t[n+i]}function A(){n=0,r=1,s=1,i=0}function C(I=0){i=I}function S(){const I=n+i;for(;I!==n;)O();i=0}return{index:f,line:d,column:m,peekOffset:h,charAt:y,currentChar:v,currentPeek:w,next:O,peek:E,reset:A,resetPeek:C,skipToPeek:S}}const _n=void 0,ay=".",Vu="'",ly="tokenizer";function cy(e,t={}){const n=t.location!==!1,r=oy(e),s=()=>r.index(),i=()=>Xb(r.line(),r.column(),r.index()),o=i(),a=s(),l={currentType:14,offset:a,startLoc:o,endLoc:o,lastType:14,lastOffset:a,lastStartLoc:o,lastEndLoc:o,braceNest:0,inLinked:!1,text:""},u=()=>l,{onError:c}=t;function f(p,_,T,...M){const K=u();if(_.column+=T,_.offset+=T,c){const U=n?ro(K.startLoc,_):null,L=is(p,U,{domain:ly,args:M});c(L)}}function d(p,_,T){p.endLoc=i(),p.currentType=_;const M={type:_};return n&&(M.loc=ro(p.startLoc,p.endLoc)),T!=null&&(M.value=T),M}const m=p=>d(p,14);function h(p,_){return p.currentChar()===_?(p.next(),_):(f(oe.EXPECTED_TOKEN,i(),0,_),"")}function y(p){let _="";for(;p.currentPeek()===Zt||p.currentPeek()===at;)_+=p.currentPeek(),p.peek();return _}function v(p){const _=y(p);return p.skipToPeek(),_}function w(p){if(p===_n)return!1;const _=p.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_===95}function O(p){if(p===_n)return!1;const _=p.charCodeAt(0);return _>=48&&_<=57}function E(p,_){const{currentType:T}=_;if(T!==2)return!1;y(p);const M=w(p.currentPeek());return p.resetPeek(),M}function A(p,_){const{currentType:T}=_;if(T!==2)return!1;y(p);const M=p.currentPeek()==="-"?p.peek():p.currentPeek(),K=O(M);return p.resetPeek(),K}function C(p,_){const{currentType:T}=_;if(T!==2)return!1;y(p);const M=p.currentPeek()===Vu;return p.resetPeek(),M}function S(p,_){const{currentType:T}=_;if(T!==8)return!1;y(p);const M=p.currentPeek()===".";return p.resetPeek(),M}function I(p,_){const{currentType:T}=_;if(T!==9)return!1;y(p);const M=w(p.currentPeek());return p.resetPeek(),M}function $(p,_){const{currentType:T}=_;if(!(T===8||T===12))return!1;y(p);const M=p.currentPeek()===":";return p.resetPeek(),M}function P(p,_){const{currentType:T}=_;if(T!==10)return!1;const M=()=>{const U=p.currentPeek();return U==="{"?w(p.peek()):U==="@"||U==="%"||U==="|"||U===":"||U==="."||U===Zt||!U?!1:U===at?(p.peek(),M()):Q(p,!1)},K=M();return p.resetPeek(),K}function q(p){y(p);const _=p.currentPeek()==="|";return p.resetPeek(),_}function ie(p){const _=y(p),T=p.currentPeek()==="%"&&p.peek()==="{";return p.resetPeek(),{isModulo:T,hasSpace:_.length>0}}function Q(p,_=!0){const T=(K=!1,U="",L=!1)=>{const R=p.currentPeek();return R==="{"?U==="%"?!1:K:R==="@"||!R?U==="%"?!0:K:R==="%"?(p.peek(),T(K,"%",!0)):R==="|"?U==="%"||L?!0:!(U===Zt||U===at):R===Zt?(p.peek(),T(!0,Zt,L)):R===at?(p.peek(),T(!0,at,L)):!0},M=T();return _&&p.resetPeek(),M}function le(p,_){const T=p.currentChar();return T===_n?_n:_(T)?(p.next(),T):null}function je(p){const _=p.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_>=48&&_<=57||_===95||_===36}function Ce(p){return le(p,je)}function ee(p){const _=p.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_>=48&&_<=57||_===95||_===36||_===45}function ae(p){return le(p,ee)}function de(p){const _=p.charCodeAt(0);return _>=48&&_<=57}function xe(p){return le(p,de)}function pe(p){const _=p.charCodeAt(0);return _>=48&&_<=57||_>=65&&_<=70||_>=97&&_<=102}function Ee(p){return le(p,pe)}function be(p){let _="",T="";for(;_=xe(p);)T+=_;return T}function et(p){v(p);const _=p.currentChar();return _!=="%"&&f(oe.EXPECTED_TOKEN,i(),0,_),p.next(),"%"}function Be(p){let _="";for(;;){const T=p.currentChar();if(T==="{"||T==="}"||T==="@"||T==="|"||!T)break;if(T==="%")if(Q(p))_+=T,p.next();else break;else if(T===Zt||T===at)if(Q(p))_+=T,p.next();else{if(q(p))break;_+=T,p.next()}else _+=T,p.next()}return _}function We(p){v(p);let _="",T="";for(;_=ae(p);)T+=_;return p.currentChar()===_n&&f(oe.UNTERMINATED_CLOSING_BRACE,i(),0),T}function Le(p){v(p);let _="";return p.currentChar()==="-"?(p.next(),_+=`-${be(p)}`):_+=be(p),p.currentChar()===_n&&f(oe.UNTERMINATED_CLOSING_BRACE,i(),0),_}function F(p){return p!==Vu&&p!==at}function Y(p){v(p),h(p,"'");let _="",T="";for(;_=le(p,F);)_==="\\"?T+=W(p):T+=_;const M=p.currentChar();return M===at||M===_n?(f(oe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,i(),0),M===at&&(p.next(),h(p,"'")),T):(h(p,"'"),T)}function W(p){const _=p.currentChar();switch(_){case"\\":case"'":return p.next(),`\\${_}`;case"u":return J(p,_,4);case"U":return J(p,_,6);default:return f(oe.UNKNOWN_ESCAPE_SEQUENCE,i(),0,_),""}}function J(p,_,T){h(p,_);let M="";for(let K=0;K<T;K++){const U=Ee(p);if(!U){f(oe.INVALID_UNICODE_ESCAPE_SEQUENCE,i(),0,`\\${_}${M}${p.currentChar()}`);break}M+=U}return`\\${_}${M}`}function _e(p){return p!=="{"&&p!= Line truncated
`,o=t.needIndent?t.needIndent:n!=="arrow",a=e.helpers||[],l=by(e,{mode:n,filename:r,sourceMap:s,breakLineCode:i,needIndent:o});l.push(n==="normal"?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(o),a.length>0&&(l.push(`const { ${Th(a.map(f=>`${f}: _${f}`),", ")} } = ctx`),l.newline()),l.push("return "),Yr(l,e),l.deindent(o),l.push("}"),delete e.helpers;const{code:u,map:c}=l.context();return{ast:e,code:u,map:c?c.toJSON():void 0}};function Oy(e,t={}){const n=Ah({},t),r=!!n.jit,s=!!n.minify,i=n.optimize==null?!0:n.optimize,a=my(n).parse(e);return r?(i&&gy(a),s&&Nr(a),{ast:a,code:""}):(py(a,n),Ty(a,n))}/*!
* core-base v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/function Sy(){typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(rn().__INTLIFY_PROD_DEVTOOLS__=!1),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(rn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(rn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}const Wn=[];Wn[0]={w:[0],i:[3,0],"[":[4],o:[7]};Wn[1]={w:[1],".":[2],"[":[4],o:[7]};Wn[2]={w:[2],i:[3,0],0:[3,0]};Wn[3]={i:[3,0],0:[3,0],w:[1,1],".":[2,1],"[":[4,1],o:[7,1]};Wn[4]={"'":[5,0],'"':[6,0],"[":[4,2],"]":[1,3],o:8,l:[4,0]};Wn[5]={"'":[4,0],o:8,l:[5,0]};Wn[6]={'"':[4,0],o:8,l:[6,0]};const Cy=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function Ny(e){return Cy.test(e)}function Ly(e){const t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t===n&&(t===34||t===39)?e.slice(1,-1):e}function Iy(e){if(e==null)return"o";switch(e.charCodeAt(0)){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function Py(e){const t=e.trim();return e.charAt(0)==="0"&&isNaN(parseInt(e))?!1:Ny(t)?Ly(t):"*"+t}function Ry(e){const t=[];let n=-1,r=0,s=0,i,o,a,l,u,c,f;const d=[];d[0]=()=>{o===void 0?o=a:o+=a},d[1]=()=>{o!==void 0&&(t.push(o),o=void 0)},d[2]=()=>{d[0](),s++},d[3]=()=>{if(s>0)s--,r=4,d[0]();else{if(s=0,o===void 0||(o=Py(o),o===!1))return!1;d[1]()}};function m(){const h=e[n+1];if(r===5&&h==="'"||r===6&&h==='"')return n++,a="\\"+h,d[0](),!0}for(;r!==null;)if(n++,i=e[n],!(i==="\\"&&m())){if(l=Iy(i),f=Wn[r],u=f[l]||f.l||8,u===8||(r=u[0],u[1]!==void 0&&(c=d[u[1]],c&&(a=i,c()===!1))))return;if(r===7)return t}}const Yu=new Map;function xy(e,t){return Se(e)?e[t]:null}function ky(e,t){if(!Se(e))return null;let n=Yu.get(t);if(n||(n=Ry(t),n&&Yu.set(t,n)),!n)return null;const r=n.length;let s=e,i=0;for(;i<r;){const o=s[n[i]];if(o===void 0||Re(s))return null;s=o,i++}return s}const $y=e=>e,Dy=e=>"",My="text",Fy=e=>e.length===0?"":Gb(e),jy=zb;function Ku(e,t){return e=Math.abs(e),t===2?e?e>1?1:0:1:e?Math.min(e,2):0}function Uy(e){const t=Ke(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(Ke(e.named.count)||Ke(e.named.n))?Ke(e.named.count)?e.named.count:Ke(e.named.n)?e.named.n:t:t}function Hy(e,t){t.count||(t.count=e),t.n||(t.n=e)}function Vy(e={}){const t=e.locale,n=Uy(e),r=Se(e.pluralRules)&&G(t)&&Re(e.pluralRules[t])?e.pluralRules[t]:Ku,s=Se(e.pluralRules)&&G(t)&&Re(e.pluralRules[t])?Ku:void 0,i=w=>w[r(n,w.length,s)],o=e.list||[],a=w=>o[w],l=e.named||{};Ke(e.pluralIndex)&&Hy(n,l);const u=w=>l[w];function c(w){const O=Re(e.messages)?e.messages(w):Se(e.messages)?e.messages[w]:!1;return O||(e.parent?e.parent.message(w):Dy)}const f=w=>e.modifiers?e.modifiers[w]:$y,d=fe(e.processor)&&Re(e.processor.normalize)?e.processor.normalize:Fy,m=fe(e.processor)&&Re(e.processor.interpolate)?e.processor.interpolate:jy,h=fe(e.processor)&&G(e.processor.type)?e.processor.type:My,v={list:a,named:u,plural:i,linked:(w,...O)=>{const[E,A]=O;let C="text",S="";O.length===1?Se(E)?(S=E.modifier||S,C=E.type||C):G(E)&&(S=E||S):O.length===2&&(G(E)&&(S=E||S),G(A)&&(C=A||C));const I=c(w)(v),$=C==="vnode"&&De(I)&&S?I[0]:I;return S?f(S)($,C):$},message:c,type:h,interpolate:m,normalize:d,values:nt({},o,l)};return v}let Us=null;function By(e){Us=e}function Wy(e,t,n){Us&&Us.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const Yy=Ky("function:translate");function Ky(e){return t=>Us&&Us.emit(e,t)}const Oh=ac.__EXTEND_POINT__,Xn=Io(Oh),zy={NOT_FOUND_KEY:Oh,FALLBACK_TO_TRANSLATE:Xn(),CANNOT_FORMAT_NUMBER:Xn(),FALLBACK_TO_NUMBER_FORMAT:Xn(),CANNOT_FORMAT_DATE:Xn(),FALLBACK_TO_DATE_FORMAT:Xn(),EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER:Xn(),__EXTEND_POINT__:Xn()},Sh=oe.__EXTEND_POINT__,Jn=Io(Sh),$t={INVALID_ARGUMENT:Sh,INVALID_DATE_ARGUMENT:Jn(),INVALID_ISO_DATE_ARGUMENT:Jn(),NOT_SUPPORT_NON_STRING_MESSAGE:Jn(),NOT_SUPPORT_LOCALE_PROMISE_VALUE:Jn(),NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:Jn(),NOT_SUPPORT_LOCALE_TYPE:Jn(),__EXTEND_POINT__:Jn()};function Kt(e){return is(e,null,void 0)}function cc(e,t){return t.locale!=null?zu(t.locale):zu(e.locale)}let la;function zu(e){if(G(e))return e;if(Re(e)){if(e.resolvedOnce&&la!=null)return la;if(e.constructor.name==="Function"){const t=e();if(Kb(t))throw Kt($t.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return la=t}else throw Kt($t.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}else throw Kt($t.NOT_SUPPORT_LOCALE_TYPE)}function Gy(e,t,n){return[...new Set([n,...De(t)?t:Se(t)?Object.keys(t):G(t)?[t]:[n]])]}function Ch(e,t,n){const r=G(n)?n:Kr,s=e;s.__localeChainCache||(s.__localeChainCache=new Map);let i=s.__localeChainCache.get(r);if(!i){i=[];let o=[n];for(;De(o);)o=Gu(i,o,t);const a=De(t)||!fe(t)?t:t.default?t.default:null;o=G(a)?[a]:a,De(o)&&Gu(i,o,!1),s.__localeChainCache.set(r,i)}return i}function Gu(e,t,n){let r=!0;for(let s=0;s<t.length&&ve(r);s++){const i=t[s];G(i)&&(r=qy(e,t[s],n))}return r}function qy(e,t,n){let r;const s=t.split("-");do{const i=s.join("-");r=Xy(e,i,n),s.splice(-1,1)}while(s.length&&r===!0);return r}function Xy(e,t,n){let rLine truncated
* vue-i18n v9.13.1
* (c) 2024 kazuya kawaguchi
* Released under the MIT License.
*/const hE="9.13.1";function pE(){typeof __VUE_I18N_FULL_INSTALL__!="boolean"&&(rn().__VUE_I18N_FULL_INSTALL__=!0),typeof __VUE_I18N_LEGACY_API__!="boolean"&&(rn().__VUE_I18N_LEGACY_API__=!0),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(rn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(rn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(rn().__INTLIFY_PROD_DEVTOOLS__=!1)}const jh=zy.__EXTEND_POINT__,en=Io(jh);en(),en(),en(),en(),en(),en(),en(),en(),en();const Uh=$t.__EXTEND_POINT__,dt=Io(Uh),ze={UNEXPECTED_RETURN_TYPE:Uh,INVALID_ARGUMENT:dt(),MUST_BE_CALL_SETUP_TOP:dt(),NOT_INSTALLED:dt(),NOT_AVAILABLE_IN_LEGACY_MODE:dt(),REQUIRED_VALUE:dt(),INVALID_VALUE:dt(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:dt(),NOT_INSTALLED_WITH_PROVIDE:dt(),UNEXPECTED_ERROR:dt(),NOT_COMPATIBLE_LEGACY_VUE_I18N:dt(),BRIDGE_SUPPORT_VUE_2_ONLY:dt(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:dt(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:dt(),__EXTEND_POINT__:dt()};function Qe(e,...t){return is(e,null,void 0)}const rl=Bn("__translateVNode"),sl=Bn("__datetimeParts"),il=Bn("__numberParts"),Hh=Bn("__setPluralRules"),Vh=Bn("__injectWithOption"),ol=Bn("__dispose");function Hs(e){if(!Se(e))return e;for(const t in e)if(no(e,t))if(!t.includes("."))Se(e[t])&&Hs(e[t]);else{const n=t.split("."),r=n.length-1;let s=e,i=!1;for(let o=0;o<r;o++){if(n[o]in s||(s[n[o]]={}),!Se(s[n[o]])){i=!0;break}s=s[n[o]]}i||(s[n[r]]=e[t],delete e[t]),Se(s[n[r]])&&Hs(s[n[r]])}return e}function Ro(e,t){const{messages:n,__i18n:r,messageResolver:s,flatJson:i}=t,o=fe(n)?n:De(r)?{}:{[e]:{}};if(De(r)&&r.forEach(a=>{if("locale"in a&&"resource"in a){const{locale:l,resource:u}=a;l?(o[l]=o[l]||{},Hi(u,o[l])):Hi(u,o)}else G(a)&&Hi(JSON.parse(a),o)}),s==null&&i)for(const a in o)no(o,a)&&Hs(o[a]);return o}function Bh(e){return e.type}function Wh(e,t,n){let r=Se(t.messages)?t.messages:{};"__i18nGlobal"in n&&(r=Ro(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const s=Object.keys(r);s.length&&s.forEach(i=>{e.mergeLocaleMessage(i,r[i])});{if(Se(t.datetimeFormats)){const i=Object.keys(t.datetimeFormats);i.length&&i.forEach(o=>{e.mergeDateTimeFormat(o,t.datetimeFormats[o])})}if(Se(t.numberFormats)){const i=Object.keys(t.numberFormats);i.length&&i.forEach(o=>{e.mergeNumberFormat(o,t.numberFormats[o])})}}}function lf(e){return ye(Js,null,e,0)}const cf="__INTLIFY_META__",uf=()=>[],gE=()=>!1;let ff=0;function df(e){return(t,n,r,s)=>e(n,r,Wr()||void 0,s)}const _E=()=>{const e=Wr();let t=null;return e&&(t=Bh(e)[cf])?{[cf]:t}:null};function fc(e={},t){const{__root:n,__injectWithOption:r}=e,s=n===void 0,i=e.flatJson,o=to?ge:Ql,a=!!e.translateExistCompatible;let l=ve(e.inheritLocale)?e.inheritLocale:!0;const u=o(n&&l?n.locale.value:G(e.locale)?e.locale:Kr),c=o(n&&l?n.fallbackLocale.value:G(e.fallbackLocale)||De(e.fallbackLocale)||fe(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:u.value),f=o(Ro(u.value,e)),d=o(fe(e.datetimeFormats)?e.datetimeFormats:{[u.value]:{}}),m=o(fe(e.numberFormats)?e.numberFormats:{[u.value]:{}});let h=n?n.missingWarn:ve(e.missingWarn)||xn(e.missingWarn)?e.missingWarn:!0,y=n?n.fallbackWarn:ve(e.fallbackWarn)||xn(e.fallbackWarn)?e.fallbackWarn:!0,v=n?n.fallbackRoot:ve(e.fallbackRoot)?e.fallbackRoot:!0,w=!!e.fallbackFormat,O=Re(e.missing)?e.missing:null,E=Re(e.missing)?df(e.missing):null,A=Re(e.postTranslation)?e.postTranslation:null,C=n?n.warnHtmlMessage:ve(e.warnHtmlMessage)?e.warnHtmlMessage:!0,S=!!e.escapeParameter;const I=n?n.modifiers:fe(e.modifiers)?e.modifiers:{};let $=e.pluralRules||n&&n.pluralRules,P;P=(()=>{s&&Qu(null);const L={version:hE,locale:u.value,fallbackLocale:c.value,messages:f.value,modifiers:I,pluralRules:$,missing:E===null?void 0:E,missingWarn:h,fallbackWarn:y,fallbackFormat:w,unresolving:!0,postTranslation:A===null?void 0:A,warnHtmlMessage:C,escapeParameter:S,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};L.datetimeFormats=d.value,L.numberFormats=m.value,L.__datetimeFormatters=fe(P)?P.__datetimeFormatters:void 0,L.__numberFormatters=fe(P)?P.__numberFormatters:void 0;const R=sE(L);return s&&Qu(R),R})(),hs(P,u.value,c.value);function ie(){return[u.value,c.value,f.value,d.value,m.value]}const Q=ne({get:()=>u.value,set:L=>{u.value=L,P.locale=u.value}}),le=ne({get:()=>c.value,set:L=>{c.value=L,P.fallbackLocale=c.value,hs(P,u.value,L)}}),je=ne(()=>f.value),Ce=ne(()=>d.value),ee=ne(()=>m.value);function ae(){return Re(A)?A:null}function de(L){A=L,P.postTranslation=L}function xe(){return O}function pe(L){L!==null&&(E=df(L)),O=L,P.missing=E}const Ee=(L,R,te,se,Pe,rt)=>{ie();let vt;try{__INTLIFY_PROD_DEVTOOLS__,s||(P.fallbackContext=n?rE():void 0),vt=L(P)}finally{__INTLIFY_PROD_DEVTOOLS__,s||(P.fallbackContext=void 0)}if(te!=="translate exists"&&Ke(vt)&&vt===Po||te==="translate exists"&&!vt){const[di,Ar]=R();return n&&v?se(n):Pe(di)}else{if(rt(vt))return vt;throw Qe(ze.UNEXPECTED_RETURN_TYPE)}};function be(...L){return Ee(RLine truncated
* vue-router v4.3.3
* (c) 2024 Eduardo San Martin Morote
* @license MIT
*/const Lr=typeof document<"u";function UE(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const Ne=Object.assign;function ua(e,t){const n={};for(const r in t){const s=t[r];n[r]=jt(s)?s.map(e):e(s)}return n}const Cs=()=>{},jt=Array.isArray,zh=/#/g,HE=/&/g,VE=/\//g,BE=/=/g,WE=/\?/g,Gh=/\+/g,YE=/%5B/g,KE=/%5D/g,qh=/%5E/g,zE=/%60/g,Xh=/%7B/g,GE=/%7C/g,Jh=/%7D/g,qE=/%20/g;function mc(e){return encodeURI(""+e).replace(GE,"|").replace(YE,"[").replace(KE,"]")}function XE(e){return mc(e).replace(Xh,"{").replace(Jh,"}").replace(qh,"^")}function ll(e){return mc(e).replace(Gh,"%2B").replace(qE,"+").replace(zh,"%23").replace(HE,"%26").replace(zE,"`").replace(Xh,"{").replace(Jh,"}").replace(qh,"^")}function JE(e){return ll(e).replace(BE,"%3D")}function QE(e){return mc(e).replace(zh,"%23").replace(WE,"%3F")}function ZE(e){return e==null?"":QE(e).replace(VE,"%2F")}function Vs(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const e1=/\/$/,t1=e=>e.replace(e1,"");function fa(e,t,n="/"){let r,s={},i="",o="";const a=t.indexOf("#");let l=t.indexOf("?");return a<l&&a>=0&&(l=-1),l>-1&&(r=t.slice(0,l),i=t.slice(l+1,a>-1?a:t.length),s=e(i)),a>-1&&(r=r||t.slice(0,a),o=t.slice(a,t.length)),r=i1(r??t,n),{fullPath:r+(i&&"?")+i+o,path:r,query:s,hash:Vs(o)}}function n1(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function yf(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function r1(e,t,n){const r=t.matched.length-1,s=n.matched.length-1;return r>-1&&r===s&&Gr(t.matched[r],n.matched[s])&&Qh(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Gr(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Qh(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!s1(e[n],t[n]))return!1;return!0}function s1(e,t){return jt(e)?Ef(e,t):jt(t)?Ef(t,e):e===t}function Ef(e,t){return jt(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function i1(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),s=r[r.length-1];(s===".."||s===".")&&r.push("");let i=n.length-1,o,a;for(o=0;o<r.length;o++)if(a=r[o],a!==".")if(a==="..")i>1&&i--;else break;return n.slice(0,i).join("/")+"/"+r.slice(o).join("/")}var Bs;(function(e){e.pop="pop",e.push="push"})(Bs||(Bs={}));var Ns;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Ns||(Ns={}));function o1(e){if(!e)if(Lr){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),t1(e)}const a1=/^[^#]+#/;function l1(e,t){return e.replace(a1,"#")+t}function c1(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const xo=()=>({left:window.scrollX,top:window.scrollY});function u1(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),s=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!s)return;t=c1(s,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function wf(e,t){return(history.state?history.state.position-t:-1)+e}const cl=new Map;function f1(e,t){cl.set(e,t)}function d1(e){const t=cl.get(e);return cl.delete(e),t}let m1=()=>location.protocol+"//"+location.host;function Zh(e,t){const{pathname:n,search:r,hash:s}=t,i=e.indexOf("#");if(i>-1){let a=s.includes(e.slice(i))?e.slice(i).length:1,l=s.slice(a);return l[0]!=="/"&&(l="/"+l),yf(l,"")}return yf(n,e)+r+s}function h1(e,t,n,r){let s=[],i=[],o=null;const a=({state:d})=>{const m=Zh(e,location),h=n.value,y=t.value;let v=0;if(d){if(n.value=m,t.value=d,o&&o===h){o=null;return}v=y?d.position-y.position:0}else r(m);s.forEach(w=>{w(n.value,h,{delta:v,type:Bs.pop,direction:v?v>0?Ns.forward:Ns.back:Ns.unknown})})};function l(){o=n.value}function u(d){s.push(d);const m=()=>{const h=s.indexOf(d);h>-1&&s.splice(h,1)};return i.push(m),m}function c(){const{history:d}=window;d.state&&d.replaceState(Ne({},d.state,{scroll:xo()}),"")}function f(){for(const d of i)d();i=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",c)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",c,{passive:!0}),{pauseListeners:l,listen:u,destroy:f}}function Af(e,t,n,r=!1,s=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:s?xo():null}}function p1(e){const{history:t,location:n}=window,r={value:Zh(e,n)},s={value:t.state};s.value||i(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(l,u,c){const f=e.indexOf("#"),d=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+l:m1()+e+l;try{t[c?"replaceState":"pushState"](u,"",d),s.value=u}catch(m){console.error(m),n[c?"replace":"assignLine truncated
`).forEach(function(o){s=o.indexOf(":"),n=o.substring(0,s).trim().toLowerCase(),r=o.substring(s+1).trim(),!(!n||t[n]&&cw[n])&&(n==="set-cookie"?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t},Bf=Symbol("internals");function gs(e){return e&&String(e).trim().toLowerCase()}function Bi(e){return e===!1||e==null?e:x.isArray(e)?e.map(Bi):String(e)}function fw(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}const dw=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function pa(e,t,n,r,s){if(x.isFunction(r))return r.call(this,t,n);if(s&&(t=n),!!x.isString(t)){if(x.isString(r))return t.indexOf(r)!==-1;if(x.isRegExp(r))return r.test(t)}}function mw(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,n,r)=>n.toUpperCase()+r)}function hw(e,t){const n=x.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(s,i,o){return this[r].call(this,t,s,i,o)},configurable:!0})})}class gt{constructor(t){t&&this.set(t)}set(t,n,r){const s=this;function i(a,l,u){const c=gs(l);if(!c)throw new Error("header name must be a non-empty string");const f=x.findKey(s,c);(!f||s[f]===void 0||u===!0||u===void 0&&s[f]!==!1)&&(s[f||l]=Bi(a))}const o=(a,l)=>x.forEach(a,(u,c)=>i(u,c,l));if(x.isPlainObject(t)||t instanceof this.constructor)o(t,n);else if(x.isString(t)&&(t=t.trim())&&!dw(t))o(uw(t),n);else if(x.isHeaders(t))for(const[a,l]of t.entries())i(l,a,r);else t!=null&&i(n,t,r);return this}get(t,n){if(t=gs(t),t){const r=x.findKey(this,t);if(r){const s=this[r];if(!n)return s;if(n===!0)return fw(s);if(x.isFunction(n))return n.call(this,s,r);if(x.isRegExp(n))return n.exec(s);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,n){if(t=gs(t),t){const r=x.findKey(this,t);return!!(r&&this[r]!==void 0&&(!n||pa(this,this[r],r,n)))}return!1}delete(t,n){const r=this;let s=!1;function i(o){if(o=gs(o),o){const a=x.findKey(r,o);a&&(!n||pa(r,r[a],a,n))&&(delete r[a],s=!0)}}return x.isArray(t)?t.forEach(i):i(t),s}clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const i=n[r];(!t||pa(this,this[i],i,t,!0))&&(delete this[i],s=!0)}return s}normalize(t){const n=this,r={};return x.forEach(this,(s,i)=>{const o=x.findKey(r,i);if(o){n[o]=Bi(s),delete n[i];return}const a=t?mw(i):String(i).trim();a!==i&&delete n[i],n[a]=Bi(s),r[a]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const n=Object.create(null);return x.forEach(this,(r,s)=>{r!=null&&r!==!1&&(n[s]=t&&x.isArray(r)?r.join(", "):r)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).join(`
`)}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}static accessor(t){const r=(this[Bf]=this[Bf]={accessors:{}}).accessors,s=this.prototype;function i(o){const a=gs(o);r[a]||(hw(s,o),r[a]=!0)}return x.isArray(t)?t.forEach(i):i(t),this}}gt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);x.reduceDescriptors(gt.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});x.freezeMethods(gt);function ga(e,t){const n=this||ti,r=t||n,s=gt.from(r.headers);let i=r.data;return x.forEach(e,function(a){i=a.call(n,i,s.normalize(),t?t.status:void 0)}),s.normalize(),i}function Ep(e){return!!(e&&e.__CANCEL__)}function as(e,t,n){me.call(this,e??"canceled",me.ERR_CANCELED,t,n),this.name="CanceledError"}x.inherits(as,me,{__CANCEL__:!0});function wp(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new me("Request failed with status code "+n.status,[me.ERR_BAD_REQUEST,me.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function pw(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function gw(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,i=0,o;return t=t!==void 0?t:1e3,function(l){const u=Date.now(),c=r[i];o||(o=u),n[s]=l,r[s]=u;let f=i,d=0;for(;f!==s;)d+=n[f++],f=f%e;if(s=(s+1)%e,s===i&&(i=(i+1)%e),u-o<t)return;const m=c&&u-c;return m?Math.round(d*1e3/m):void 0}}function _w(e,t){let n=0,r=1e3/t,s,i;const o=(u,c=Date.now())=>{n=c,s=null,i&&(clearTimeout(i),i=null),e.apply(null,u)};return[(...u)=>{const c=Date.now(),f=c-n;f>=r?o(u,c):(s=u,i||(i=setTimeout(()=>{i=null,o(s)},r-f)))},()=>s&&o(s)]}const so=(e,t,n=3)=>{let r=0;const s=gw(50,250);return _w(i=>{const o=i.loaded,a=i.lengthComputable?i.total:void 0,l=o-r,u=s(l),c=o<=a;r=o;const f={loaded:o,total:a,progress:a?o/a:void 0,bytes:l,rate:u||void 0,estimated:u&&a&&c?(a-o)/u:void 0,event:i,lengthComputable:a!=null,[t?"download":"upload"]:!0};e(f)},n)},Wf=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},Yf=e=>(...t)=>x.asap(()=>e(...t)),vw=Ft.hasStandardBrowserEnv?function(){const t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");let r;function s(i){let o=i;return t&&(n.setAttribute("href",o),o=n.href),n.setAttribute("href",o),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:n.pathname.charAt(0)==="/"?n.pathname:"/"+n.pathname}}return r=s(window.location.href),function(o){const a=x.isString(o)?s(o):o;return a.protocol===r.protocol&&a.host===r.host}}():function(){return function(){return!0}}(),bw=Ft.hasStandardBrowserEnv?{write(e,t,n,r,s,i){const o=[e+"="+encodeURIComponent(t)];x.isNumber(n)&&o.push("expires="+new Date(n).toGMTString()),x.isString(r)&&o.push("path="+r),x.isString(s)&&o.push("domain="+s),i===!0&&o.push("secure"),document.cookie=o.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read(){return null},remove(){}};function yw(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function Ew(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function Ap(e,t){return e&&!yw(t)?Ew(e,t):t}const Kf=e=>e instanceof gt?{...e}:e;function mr(e,t){t=t||{};const n={};function r(u,c,f){return x.isPlainObject(u)&&x.isPlainObject(c)?x.merge.call({caseless:f},u,c):x.isPlainObject(c)?x.merge({},c):x.isArray(c)?c.slice():c}function s(u,c,f){if(x.isUndefined(c)){if(!x.isUndefined(u))return r(void 0,u,f)}else return r(u,c,f)}function i(u,c){if(!x.isUndefined(c))return r(void 0,c)}function o(u,c){if(x.isUndefined(c)){if(!x.isUndefined(u))return r(void 0,u)}else return r(void 0,c)}function a(u,c,f){if(f in t)return r(u,c);if(f in e)return r(void 0,u)}const l={url:i,method:i,data:i,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:a,headers:(u,c)=>s(Kf(u),Kf(c),!0)};return x.forEach(Object.keys(Object.assign({},e,t)),function(c){const f=l[c]||s,d=f(e[c],t[c],c);x.isUndefined(d)&&f!==a||(n[c]=d)}),n}const Tp=e=>{const t=mr({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:s,xsrfCookieName:i,headers:o,auth:a}=t;t.headers=o=gt.from(o),t.url=vp(Ap(t.baseURL,t.url),e.params,e.paramsSerializer),a&&o.set("Authorization","Basic "+btoa((a.username||"")+":"+(a.password?unescape(encodeURIComponent(a.password)):"")));let l;if(x.isFormD Line truncated
`+i.map(qf).join(`
`):" "+qf(i[0]):"as no adapter specified";throw new me("There is no suitable adapter to dispatch the request "+o,"ERR_NOT_SUPPORT")}return r},adapters:pl};function _a(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new as(null,e)}function Xf(e){return _a(e),e.headers=gt.from(e.headers),e.data=ga.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),Cp.getAdapter(e.adapter||ti.adapter)(e).then(function(r){return _a(e),r.data=ga.call(e,e.transformResponse,r),r.headers=gt.from(r.headers),r},function(r){return Ep(r)||(_a(e),r&&r.response&&(r.response.data=ga.call(e,e.transformResponse,r.response),r.response.headers=gt.from(r.response.headers))),Promise.reject(r)})}const Np="1.7.3",vc={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{vc[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Jf={};vc.transitional=function(t,n,r){function s(i,o){return"[Axios v"+Np+"] Transitional option '"+i+"'"+o+(r?". "+r:"")}return(i,o,a)=>{if(t===!1)throw new me(s(o," has been removed"+(n?" in "+n:"")),me.ERR_DEPRECATED);return n&&!Jf[o]&&(Jf[o]=!0,console.warn(s(o," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(i,o,a):!0}};function Rw(e,t,n){if(typeof e!="object")throw new me("options must be an object",me.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let s=r.length;for(;s-- >0;){const i=r[s],o=t[i];if(o){const a=e[i],l=a===void 0||o(a,i,e);if(l!==!0)throw new me("option "+i+" must be "+l,me.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new me("Unknown option "+i,me.ERR_BAD_OPTION)}}const gl={assertOptions:Rw,validators:vc},bn=gl.validators;class ur{constructor(t){this.defaults=t,this.interceptors={request:new Vf,response:new Vf}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let s;Error.captureStackTrace?Error.captureStackTrace(s={}):s=new Error;const i=s.stack?s.stack.replace(/^.+\n/,""):"";try{r.stack?i&&!String(r.stack).endsWith(i.replace(/^.+\n.+\n/,""))&&(r.stack+=`
`+i):r.stack=i}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=mr(this.defaults,n);const{transitional:r,paramsSerializer:s,headers:i}=n;r!==void 0&&gl.assertOptions(r,{silentJSONParsing:bn.transitional(bn.boolean),forcedJSONParsing:bn.transitional(bn.boolean),clarifyTimeoutError:bn.transitional(bn.boolean)},!1),s!=null&&(x.isFunction(s)?n.paramsSerializer={serialize:s}:gl.assertOptions(s,{encode:bn.function,serialize:bn.function},!0)),n.method=(n.method||this.defaults.method||"get").toLowerCase();let o=i&&x.merge(i.common,i[n.method]);i&&x.forEach(["delete","get","head","post","put","patch","common"],h=>{delete i[h]}),n.headers=gt.concat(o,i);const a=[];let l=!0;this.interceptors.request.forEach(function(y){typeof y.runWhen=="function"&&y.runWhen(n)===!1||(l=l&&y.synchronous,a.unshift(y.fulfilled,y.rejected))});const u=[];this.interceptors.response.forEach(function(y){u.push(y.fulfilled,y.rejected)});let c,f=0,d;if(!l){const h=[Xf.bind(this),void 0];for(h.unshift.apply(h,a),h.push.apply(h,u),d=h.length,c=Promise.resolve(n);f<d;)c=c.then(h[f++],h[f++]);return c}d=a.length;let m=n;for(f=0;f<d;){const h=a[f++],y=a[f++];try{m=h(m)}catch(v){y.call(this,v);break}}try{c=Xf.call(this,m)}catch(h){return Promise.reject(h)}for(f=0,d=u.length;f<d;)c=c.then(u[f++],u[f++]);return c}getUri(t){t=mr(this.defaults,t);const n=Ap(t.baseURL,t.url);return vp(n,t.params,t.paramsSerializer)}}x.forEach(["delete","get","head","options"],function(t){ur.prototype[t]=function(n,r){return this.request(mr(r||{},{method:t,url:n,data:(r||{}).data}))}});x.forEach(["post","put","patch"],function(t){function n(r){return function(i,o,a){return this.request(mr(a||{},{method:t,headers:r?{"Content-Type":"multipart/form-data"}:{},url:i,data:o}))}}ur.prototype[t]=n(),ur.prototype[t+"Form"]=n(!0)});class bc{constructor(t){if(typeof t!="function")throw new TypeError("executor must be a function.");let n;this.promise=new Promise(function(i){n=i});const r=this;this.promise.then(s=>{if(!r._listeners)return;let i=r._listeners.length;for(;i-- >0;)r._listeners[i](s);r._listeners=null}),this.promise.then=s=>{let i;const o=new Promise(a=>{r.subscribe(a),i=a}).then(s);return o.cancel=function(){r.unsubscribe(i)},o},t(function(i,o,a){r.reason||(r.reason=new as(i,o,a),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}static source(){let t;return{token:new bc(function(s){t=s}),cancel:t}}}function xw(e){return function(n){return e.apply(null,n)}}function kw(e){return x.isObject(e)&&e.isAxiosError===!0}const _l={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(_l).forEach(([e,t])=>{_l[t]=e});function Lp(e){const t=new ur(e),n=op(ur.prototype.request,t);return x.extend(n,ur.prototype,t,{allOwnKeys:!0}),x.extend(n,t,null,{allOwnKeys:!0}),n.create=function(s){return Lp(mr(e,s))},n}const Ue=Lp(ti);Ue.Axios=ur;Ue.CanceledError=as;Ue.CancelToken=bc;Ue.isCancel=Ep;Ue.VERSION=Np;Ue.toFormData=jo;Ue.AxiosError=me;Ue.Cancel=Ue.CanceledError;Ue.all=function(t){return Promise.all(t)};Ue.spread=xw;Ue.isAxiosError=kw;Ue.mergeConfig=mr;Ue.AxiosHeaders=gt;Ue.formToJSON=e=>yp(x.isHTMLForm(e)?new FormData(e):e);Ue.getAdapter=Cp.getAdapter;Ue.HttpStatusCode=_l;Ue.default=Ue;class $w{signupUser(t){return new Promise((n,r)=>{Ue.post(`${Is.API_BASE_URL}/auth/signup`,t,{withCredentials:!0}).then(s=>{n(s.data)}).catch(s=>{r(s)})})}loginUser(t){return new Promise((n,r)=>{Ue.post(`${Is.API_BASE_URL}/auth/login`,t,{withCredentials:!0}).then(s=>{n(s)}).catch(s=>{r(s)})})}logoutUser(){return new Promise((t,n)=>{Ue.post(`${Is.API_BASE_URL}/auth/logout`,null,{withCredentials:!0}).then(r=>{t Line truncated
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/const yn=new Map,va={set(e,t,n){yn.has(e)||yn.set(e,new Map);const r=yn.get(e);if(!r.has(t)&&r.size!==0){console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(r.keys())[0]}.`);return}r.set(t,n)},get(e,t){return yn.has(e)&&yn.get(e).get(t)||null},remove(e,t){if(!yn.has(e))return;const n=yn.get(e);n.delete(t),n.size===0&&yn.delete(e)}},DA=1e6,MA=1e3,El="transitionend",tg=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,(t,n)=>`#${CSS.escape(n)}`)),e),FA=e=>e==null?`${e}`:Object.prototype.toString.call(e).match(/\s([a-z]+)/i)[1].toLowerCase(),jA=e=>{do e+=Math.floor(Math.random()*DA);while(document.getElementById(e));return e},UA=e=>{if(!e)return 0;let{transitionDuration:t,transitionDelay:n}=window.getComputedStyle(e);const r=Number.parseFloat(t),s=Number.parseFloat(n);return!r&&!s?0:(t=t.split(",")[0],n=n.split(",")[0],(Number.parseFloat(t)+Number.parseFloat(n))*MA)},ng=e=>{e.dispatchEvent(new Event(El))},an=e=>!e||typeof e!="object"?!1:(typeof e.jquery<"u"&&(e=e[0]),typeof e.nodeType<"u"),kn=e=>an(e)?e.jquery?e[0]:e:typeof e=="string"&&e.length>0?document.querySelector(tg(e)):null,cs=e=>{if(!an(e)||e.getClientRects().length===0)return!1;const t=getComputedStyle(e).getPropertyValue("visibility")==="visible",n=e.closest("details:not([open])");if(!n)return t;if(n!==e){const r=e.closest("summary");if(r&&r.parentNode!==n||r===null)return!1}return t},$n=e=>!e||e.nodeType!==Node.ELEMENT_NODE||e.classList.contains("disabled")?!0:typeof e.disabled<"u"?e.disabled:e.hasAttribute("disabled")&&e.getAttribute("disabled")!=="false",rg=e=>{if(!document.documentElement.attachShadow)return null;if(typeof e.getRootNode=="function"){const t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?rg(e.parentNode):null},ao=()=>{},ri=e=>{e.offsetHeight},sg=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,ba=[],HA=e=>{document.readyState==="loading"?(ba.length||document.addEventListener("DOMContentLoaded",()=>{for(const t of ba)t()}),ba.push(e)):e()},It=()=>document.documentElement.dir==="rtl",Rt=e=>{HA(()=>{const t=sg();if(t){const n=e.NAME,r=t.fn[n];t.fn[n]=e.jQueryInterface,t.fn[n].Constructor=e,t.fn[n].noConflict=()=>(t.fn[n]=r,e.jQueryInterface)}})},pt=(e,t=[],n=e)=>typeof e=="function"?e(...t):n,ig=(e,t,n=!0)=>{if(!n){pt(e);return}const s=UA(t)+5;let i=!1;const o=({target:a})=>{a===t&&(i=!0,t.removeEventListener(El,o),pt(e))};t.addEventListener(El,o),setTimeout(()=>{i||ng(t)},s)},kc=(e,t,n,r)=>{const s=e.length;let i=e.indexOf(t);return i===-1?!n&&r?e[s-1]:e[0]:(i+=n?1:-1,r&&(i=(i+s)%s),e[Math.max(0,Math.min(i,s-1))])},VA=/[^.]*(?=\..*)\.|.*/,BA=/\..*/,WA=/::\d+$/,ya={};let od=1;const og={mouseenter:"mouseover",mouseleave:"mouseout"},YA=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function ag(e,t){return t&&`${t}::${od++}`||e.uidEvent||od++}function lg(e){const t=ag(e);return e.uidEvent=t,ya[t]=ya[t]||{},ya[t]}function KA(e,t){return function n(r){return $c(r,{delegateTarget:e}),n.oneOff&&H.off(e,r.type,t),t.apply(e,[r])}}function zA(e,t,n){return function r(s){const i=e.querySelectorAll(t);for(let{target:o}=s;o&&o!==this;o=o.parentNode)for(const a of i)if(a===o)return $c(s,{delegateTarget:o}),r.oneOff&&H.off(e,s.type,t,n),n.apply(o,[s])}}function cg(e,t,n=null){return Object.values(e).find(r=>r.callable===t&&r.delegationSelector===n)}function ug(e,t,n){const r=typeof t=="string",s=r?n:t||n;let i=fg(e);return YA.has(i)||(i=e),[r,s,i]}function ad(e,t,n,r,s){if(typeof t!="string"||!e)return;let[i,o,a]=ug(t,n,r);t in og&&(o=(h=>function(y){if(!y.relatedTarget||y.relatedTarget!==y.delegateTarget&&!y.delegateTarget.contains(y.relatedTarget))return h.call(this,y)})(o));const l=lg(e),u=l[a]||(l[a]={}),c=cg(u,o,i?n:null);if(c){c.oneOff=c.oneOff&&s;return}const f=ag(o,t.replace(VA,"")),d=i?zA(e,n,o):KA(e,o);d.delegationSelector=i?n:null,d.callable=o,d.oneOff=s,d.uidEvent=f,u[f]=d,e.addEventListener(a,d,i)}function wl(e,t,n,r,s){const i=cg(t[n],r,s);i&&(e.removeEventListener(n,i,!!s),delete t[n][i.uidEvent])}function GA(e,t,n,r){const s=t[n]||{};for(const[i,o]of Object.entries(s))i.includes(r)&&wl(e,t,n,o.callable,o.delegationSelector)}function fg(e){return e=e.replace(BA,""),og[e]||e}const H={on(e,t,n,r){ad(e,t,n,r,!1)},one(e,t,n,r){ad(e,t,n,r,!0)},off(e,t,n,r){if(typeof t!="string"||!e)return;const[s,i,o]=ug(t,n,r),a=o!==t,l=lg(e),u=l[o]||{},c=t.startsWith(".");if(typeof i<"u"){if(!ObLine truncated
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function PI(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var Bd=function(){},Vc={},Ug={},Hg=null,Vg={mark:Bd,measure:Bd};try{typeof window<"u"&&(Vc=window),typeof document<"u"&&(Ug=document),typeof MutationObserver<"u"&&(Hg=MutationObserver),typeof performance<"u"&&(Vg=performance)}catch{}var RI=Vc.navigator||{},Wd=RI.userAgent,Yd=Wd===void 0?"":Wd,Mn=Vc,Me=Ug,Kd=Hg,Ci=Vg;Mn.document;var pn=!!Me.documentElement&&!!Me.head&&typeof Me.addEventListener=="function"&&typeof Me.createElement=="function",Bg=~Yd.indexOf("MSIE")||~Yd.indexOf("Trident/"),Ni,Li,Ii,Pi,Ri,un="___FONT_AWESOME___",Nl=16,Wg="fa",Yg="svg-inline--fa",_r="data-fa-i2svg",Ll="data-fa-pseudo-element",xI="data-fa-pseudo-element-pending",Bc="data-prefix",Wc="data-icon",zd="fontawesome-i2svg",kI="async",$I=["HTML","HEAD","STYLE","SCRIPT"],Kg=function(){try{return!0}catch{return!1}}(),$e="classic",Ve="sharp",Yc=[$e,Ve];function ci(e){return new Proxy(e,{get:function(n,r){return r in n?n[r]:n[$e]}})}var Ks=ci((Ni={},qe(Ni,$e,{fa:"solid",fas:"solid","fa-solid":"solid",far:"regular","fa-regular":"regular",fal:"light","fa-light":"light",fat:"thin","fa-thin":"thin",fad:"duotone","fa-duotone":"duotone",fab:"brands","fa-brands":"brands",fak:"kit",fakd:"kit","fa-kit":"kit","fa-kit-duotone":"kit"}),qe(Ni,Ve,{fa:"solid",fass:"solid","fa-solid":"solid",fasr:"regular","fa-regular":"regular",fasl:"light","fa-light":"light",fast:"thin","fa-thin":"thin"}),Ni)),zs=ci((Li={},qe(Li,$e,{solid:"fas",regular:"far",light:"fal",thin:"fat",duotone:"fad",brands:"fab",kit:"fak"}),qe(Li,Ve,{solid:"fass",regular:"fasr",light:"fasl",thin:"fast"}),Li)),Gs=ci((Ii={},qe(Ii,$e,{fab:"fa-brands",fad:"fa-duotone",fak:"fa-kit",fal:"fa-light",far:"fa-regular",fas:"fa-solid",fat:"fa-thin"}),qe(Ii,Ve,{fass:"fa-solid",fasr:"fa-regular",fasl:"fa-light",fast:"fa-thin"}),Ii)),DI=ci((Pi={},qe(Pi,$e,{"fa-brands":"fab","fa-duotone":"fad","fa-kit":"fak","fa-light":"fal","fa-regular":"far","fa-solid":"fas","fa-thin":"fat"}),qe(Pi,Ve,{"fa-solid":"fass","fa-regular":"fasr","fa-light":"fasl","fa-thin":"fast"}),Pi)),MI=/fa(s|r|l|t|d|b|k|ss|sr|sl|st)?[\-\ ]/,zg="fa-layers-text",FI=/Font ?Awesome ?([56 ]*)(Solid|Regular|Light|Thin|Duotone|Brands|Free|Pro|Sharp|Kit)?.*/i,jI=ci((Ri={},qe(Ri,$e,{900:"fas",400:"far",normal:"far",300:"fal",100:"fat"}),qe(Ri,Ve,{900:"fass",400:"fasr",300:"fasl",100:"fast"}),Ri)),Gg=[1,2,3,4,5,6,7,8,9,10],UI=Gg.concat([11,12,13,14,15,16,17,18,19,20]),HI=["class","data-prefix","data-icon","data-fa-transform","data-fa-mask"],ir={GROUP:"duotone-group",SWAP_OPACITY:"swap-opacity",PRIMARY:"primary",SECONDARY:"secondary"},qs=new Set;Object.keys(zs[$e]).map(qs.add.bind(qs));Object.keys(zs[Ve]).map(qs.add.bind(qs));var VI=[].concat(Yc,li(qs),["2xs","xs","sm","lg","xl","2xl","beat","border","fade","beat-fade","bounce","flip-both","flip-horizontal","flip-vertical","flip","fw","inverse","layers-counter","layers-text","layers","li","pull-left","pull-right","pulse","rotate-180","rotate-270","rotate-90","rotate-by","shake","spin-pulse","spin-reverse","spin","stack-1x","stack-2x","stack","ul",ir.GROUP,ir.SWAP_OPACITY,ir.PRIMARY,ir.SECONDARY]).concat(Gg.map(function(e){return"".concat(e,"x")})).concat(UI.map(function(e){return"w-".concat(e)})),xs=Mn.FontAwesomeConfig||{};function BI(e){var t=Me.querySelector("script["+e+"]");if(t)return t.getAttribute(e)}function WI(e){return e===""?!0:e==="false"?!1:e==="true"?!0:e}if(Me&&typeof Me.querySelector=="function"){var YI=[["data-family-prefix","familyPrefix"],["data-css-prefix","cssPrefix"],["data-family-default","familyDefault"],["data-style-default","styleDefault"],["data-replacement-class","replacementClass"],["data-auto-replace-svg","autoReplaceSvg"],["data-auto-add-css","autoAddCss"],["data-auto-a11y","autoA11y"],["data-search-pseudo-elements","searchPseudoElements"],["data-observe-mutations","observeMutations"],["data-mutate-approach","mutateApproach"],["data-keep-original-source","keepOriginalSource"],["data-measure-performance","measurePerformance"],["data-show-missing-icons","showMissingIcons"]];YI.forEach(function(e){var t=Hc(e,2),n=t[0],r=t[1],s=WI(BI(n));s!=null&&(xs[r]=s)})}var qg={styleDefault:"solid",familyDefault:"classic",cssPrefix:Wg,replacementClass:Yg,autoReplaceSvg:!0,autoAddCss:!0,autoA11y:!0,searchPseudoElements:!1,observeMutations:!0,mutateApproach:"async",keepOriginalSource:!0,measurePerformance:!1,showMissingIcons:!0};xs.familyPrefix&&(xs.cssPrefix=xs.familyPrefix);var ns=X(X({},qg),xs);ns.autoReplaceSvg||(ns.observeMutations=!1);var Z={};Object.keys(qg).forEach(function(e){Object.defineProperty(Z,e,{enumerable:!0,set:function(n){ns[e]=n,ks.forEach(function(r){return r(Z)})},get:function(){return ns[e]}})});Object.defineProperty(Z,"familyPrefix",{enumerable:!0,set:function(t){ns.cssPrefix=t,ks.forEach(function(n){return n(Z)})},get:function(){return ns.cssPrefix}});Mn.FontAwesomeConfig=Z;var ks=[];function KI(e){return ks.push(e),function(){ks.splice(ks.indexOf(e),1)}}var En=Nl,zt={size:16,x:0 Line truncated
--fa-font-solid: normal 900 1em/1 "Font Awesome 6 Solid";
--fa-font-regular: normal 400 1em/1 "Font Awesome 6 Regular";
--fa-font-light: normal 300 1em/1 "Font Awesome 6 Light";
--fa-font-thin: normal 100 1em/1 "Font Awesome 6 Thin";
--fa-font-duotone: normal 900 1em/1 "Font Awesome 6 Duotone";
--fa-font-sharp-solid: normal 900 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-regular: normal 400 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-light: normal 300 1em/1 "Font Awesome 6 Sharp";
--fa-font-sharp-thin: normal 100 1em/1 "Font Awesome 6 Sharp";
--fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
}
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
overflow: visible;
box-sizing: content-box;
}
.svg-inline--fa {
display: var(--fa-display, inline-block);
height: 1em;
overflow: visible;
vertical-align: -0.125em;
}
.svg-inline--fa.fa-2xs {
vertical-align: 0.1em;
}
.svg-inline--fa.fa-xs {
vertical-align: 0em;
}
.svg-inline--fa.fa-sm {
vertical-align: -0.0714285705em;
}
.svg-inline--fa.fa-lg {
vertical-align: -0.2em;
}
.svg-inline--fa.fa-xl {
vertical-align: -0.25em;
}
.svg-inline--fa.fa-2xl {
vertical-align: -0.3125em;
}
.svg-inline--fa.fa-pull-left {
margin-right: var(--fa-pull-margin, 0.3em);
width: auto;
}
.svg-inline--fa.fa-pull-right {
margin-left: var(--fa-pull-margin, 0.3em);
width: auto;
}
.svg-inline--fa.fa-li {
width: var(--fa-li-width, 2em);
top: 0.25em;
}
.svg-inline--fa.fa-fw {
width: var(--fa-fw-width, 1.25em);
}
.fa-layers svg.svg-inline--fa {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
}
.fa-layers-counter, .fa-layers-text {
display: inline-block;
position: absolute;
text-align: center;
}
.fa-layers {
display: inline-block;
height: 1em;
position: relative;
text-align: center;
vertical-align: -0.125em;
width: 1em;
}
.fa-layers svg.svg-inline--fa {
-webkit-transform-origin: center center;
transform-origin: center center;
}
.fa-layers-text {
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
-webkit-transform-origin: center center;
transform-origin: center center;
}
.fa-layers-counter {
background-color: var(--fa-counter-background-color, #ff253a);
border-radius: var(--fa-counter-border-radius, 1em);
box-sizing: border-box;
color: var(--fa-inverse, #fff);
line-height: var(--fa-counter-line-height, 1);
max-width: var(--fa-counter-max-width, 5em);
min-width: var(--fa-counter-min-width, 1.5em);
overflow: hidden;
padding: var(--fa-counter-padding, 0.25em 0.5em);
right: var(--fa-right, 0);
text-overflow: ellipsis;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
transform: scale(var(--fa-counter-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right;
}
.fa-layers-bottom-right {
bottom: var(--fa-bottom, 0);
right: var(--fa-right, 0);
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom right;
transform-origin: bottom right;
}
.fa-layers-bottom-left {
bottom: var(--fa-bottom, 0);
left: var(--fa-left, 0);
right: auto;
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom left;
transform-origin: bottom left;
}
.fa-layers-top-right {
top: var(--fa-top, 0);
right: var(--fa-right, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right;
}
.fa-layers-top-left {
left: var(--fa-left, 0);
right: auto;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top left;
transform-origin: top left;
}
.fa-1x {
font-size: 1em;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-6x {
font-size: 6em;
}
.fa-7x {
font-size: 7em;
}
.fa-8x {
font-size: 8em;
}
.fa-9x {
font-size: 9em;
}
.fa-10x {
font-size: 10em;
}
.fa-2xs {
font-size: 0.625em;
line-height: 0.1em;
vertical-align: 0.225em;
}
.fa-xs {
font-size: 0.75em;
line-height: 0.0833333337em;
vertical-align: 0.125em;
}
.fa-sm {
font-size: 0.875em;
line-height: 0.0714285718em;
vertical-align: 0.0535714295em;
}
.fa-lg {
font-size: 1.25em;
line-height: 0.05em;
vertical-align: -0.075em;
}
.fa-xl {
font-size: 1.5em;
line-height: 0.0416666682em;
vertical-align: -0.125em;
}
.fa-2xl {
font-size: 2em;
line-height: 0.03125em;
vertical-align: -0.1875em;
}
.fa-fw {
text-align: center;
width: 1.25em;
}
.fa-ul {
list-style-type: none;
margin-left: var(--fa-li-margin, 2.5em);
padding-left: 0;
}
.fa-ul > li {
position: relative;
}
.fa-li {
left: calc(var(--fa-li-width, 2em) * -1);
position: absolute;
text-align: center;
width: var(--fa-li-width, 2em);
line-height: inherit;
}
.fa-border {
border-color: var(--fa-border-color, #eee);
border-radius: var(--fa-border-radius, 0.1em);
border-style: var(--fa-border-style, solid);
border-width: var(--fa-border-width, 0.08em);
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em);
}
.fa-pull-left {
float: left;
margin-right: var(--fa-pull-margin, 0.3em);
}
.fa-pull-right {
float: right;
margin-left: var(--fa-pull-margin, 0.3em);
}
.fa-beat {
-webkit-animation-name: fa-beat;
animation-name: fa-beat;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-bounce {
-webkit-animation-name: fa-bounce;
animation-name: fa-bounce;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
}
.fa-fade {
-webkit-animation-name: fa-fade;
animation-name: fa-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-beat-fade {
-webkit-animation-name: fa-beat-fade;
animation-name: fa-beat-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-flip {
-webkit-animation-name: fa-flip;
animation-name: fa-flip;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-shake {
-webkit-animation-name: fa-shake;
animation-name: fa-shake;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear);
}
.fa-spin {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 2s);
animation-duration: var(--fa-animation-duration, 2s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear);
}
.fa-spin-reverse {
--fa-animation-direction: reverse;
}
.fa-pulse,
.fa-spin-pulse {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
animation-timing-function: var(--fa-animation-timing, steps(8));
}
@media (prefers-reduced-motion: reduce) {
.fa-beat,
.fa-bounce,
.fa-fade,
.fa-beat-fade,
.fa-flip,
.fa-pulse,
.fa-shake,
.fa-spin,
.fa-spin-pulse {
-webkit-animation-delay: -1ms;
animation-delay: -1ms;
-webkit-animation-duration: 1ms;
animation-duration: 1ms;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-transition-delay: 0s;
transition-delay: 0s;
-webkit-transition-duration: 0s;
transition-duration: 0s;
}
}
@-webkit-keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@-webkit-keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
}
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
}
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
}
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
}
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
}
@keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
}
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
}
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
}
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
}
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0);
}
}
@-webkit-keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4);
}
}
@keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4);
}
}
@-webkit-keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125));
}
}
@keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125));
}
}
@-webkit-keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
}
}
@keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
}
}
@-webkit-keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg);
}
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg);
}
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg);
}
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg);
}
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg);
}
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg);
}
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg);
}
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg);
}
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg);
}
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg);
}
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg);
}
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg);
}
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg);
}
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg);
}
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg);
}
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg);
}
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.fa-rotate-90 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-webkit-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
-webkit-transform: scale(1, -1);
transform: scale(1, -1);
}
.fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
-webkit-transform: scale(-1, -1);
transform: scale(-1, -1);
}
.fa-rotate-by {
-webkit-transform: rotate(var(--fa-rotate-angle, 0));
transform: rotate(var(--fa-rotate-angle, 0));
}
.fa-stack {
display: inline-block;
vertical-align: middle;
height: 2em;
position: relative;
width: 2.5em;
}
.fa-stack-1x,
.fa-stack-2x {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
z-index: var(--fa-stack-z-index, auto);
}
.svg-inline--fa.fa-stack-1x {
height: 1em;
width: 1.25em;
}
.svg-inline--fa.fa-stack-2x {
height: 2em;
width: 2.5em;
}
.fa-inverse {
color: var(--fa-inverse, #fff);
}
.sr-only,
.fa-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.sr-only-focusable:not(:focus),
.fa-sr-only-focusable:not(:focus) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.svg-inline--fa .fa-primary {
fill: var(--fa-primary-color, currentColor);
opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa .fa-secondary {
fill: var(--fa-secondary-color, currentColor);
opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-primary {
opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-secondary {
opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa mask .fa-primary,
.svg-inline--fa mask .fa-secondary {
fill: black;
}
.fad.fa-inverse,
.fa-duotone.fa-inverse {
color: var(--fa-inverse, #fff);
}`;function Jg(){var e=Wg,t=Yg,n=Z.cssPrefix,r=Z.replacementClass,s=QI;if(n!==e||r!==t){var i=new RegExp("\\.".concat(e,"\\-"),"g"),o=new RegExp("\\--".concat(e,"\\-"),"g"),a=new RegExp("\\.".concat(t),"g");s=s.replace(i,".".concat(n,"-")).replace(o,"--".concat(n,"-")).replace(a,".".concat(r))}return s}var Gd=!1;function ka(){Z.autoAddCss&&!Gd&&(zI(Jg()),Gd=!0)}var ZI={mixout:function(){return{dom:{css:Jg,insertCss:ka}}},hooks:function(){return{beforeDOMElementCreation:function(){ka()},beforeI2svg:function(){ka()}}}},fn=Mn||{};fn[un]||(fn[un]={});fn[un].styles||(fn[un].styles={});fn[un].hooks||(fn[un].hooks={});fn[un].shims||(fn[un].shims=[]);var Dt=fn[un],Qg=[],eP=function e(){Me.removeEventListener("DOMContentLoaded",e),mo=1,Qg.map(function(t){return t()})},mo=!1;pn&&(mo=(Me.documentElement.doScroll?/^loaded|^c/:/^loaded|^i|^c/).test(Me.readyState),mo||Me.addEventListener("DOMContentLoaded",eP));function tP(e){pn&&(mo?setTimeout(e,0):Qg.push(e))}function ui(e){var t=e.tag,n=e.attributes,r=n===void 0?{}:n,s=e.children,i=s===void 0?[]:s;return typeof e=="string"?Xg(e):"<".concat(t," ").concat(qI(r),">").concat(i.map(ui).join(""),"</").concat(t,">")}function qd(e,t,n){if(e&&e[t]&&e[t][n])return{prefix:t,iconName:n,icon:e[t][n]}}var $a=function(t,n,r,s){var i=Object.keys(t),o=i.length,a=n,l,u,c;for(r===void 0?(l=1,c=t[i[0]]):(l=0,c=r);l<o;l++)u=i[l],c=a(c,t[u],u,t);return c};function nP(e){for(var t=[],n=0,r=e.length;n<r;){var s=e.charCodeAt(n++);if(s>=55296&&s<=56319&&n<r){var i=e.charCodeAt(n++);(i&64512)==56320?t.push(((s&1023)<<10)+(i&1023)+65536):(t.push(s),n--)}else t.push(s)}return t}function Il(e){var t=nP(e);return t.length===1?t[0].toString(16):null}function rP(e,t){var n=e.length,r=e.charCodeAt(t),s;return r>=55296&&r<=56319&&n>t+1&&(s=e.charCodeAt(t+1),s>=56320&&s<=57343)?(r-55296)*1024+s-56320+65536:r}function Xd(e){return Object.keys(e).reduce(function(t,n){var r=e[n],s=!!r.icon;return s?t[r.iconName]=r.icon:t[n]=r,t},{})}function Pl(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.skipHooks,s=r===void 0?!1:r,i=Xd(t);typeof Dt.hooks.addPack=="function"&&!s?Dt.hooks.addPack(e,Xd(t)):Dt.styles[e]=X(X({},Dt.styles[e]||{}),i),e==="fas"&&Pl("fa",t)}var xi,ki,$i,$r=Dt.styles,sP=Dt.shims,iP=(xi={},qe(xi,$e,Object.values(Gs[$e])),qe(xi,Ve,Object.values(Gs[Ve])),xi),Gc=null,Zg={},e_={},t_={},n_={},r_={},oP=(ki={},qe(ki,$e,Object.keys(Ks[$e])),qe(ki,Ve,Object.keys(Ks[Ve])),ki);function aP(e){return~VI.indexOf(e)}function lP(e,t){var n=t.split("-"),r=n[0],s=n.slice(1).join("-");return r===e&&s!==""&&!aP(s)?s:null}var s_=function(){var t=function(i){return $a($r,function(o,a,l){return o[l]=$a(a,i,{}),o},{})};Zg=t(function(s,i,o){if(i[3]&&(s[i[3]]=o),i[2]){var a=i[2].filter(function(l){return typeof l=="number"});a.forEach(function(l){s[l.toString(16)]=o})}return s}),e_=t(function(s,i,o){if(s[o]=o,i[2]){var a=i[2].filter(function(l){return typeof l=="string"});a.forEach(function(l){s[l]=o})}return s}),r_=t(function(s,i,o){var a=i[2];return s[o]=o,a.forEach(function(l){s[l]=o}),s});var n="far"in $r||Z.autoFetchSvg,r=$a(sP,function(s,i){var o=i[0],a=i[1],l=i[2];return a==="far"&&!n&&(a="fas"),typeof o=="string"&&(s.names[o]={prefix:a,iconName:l}),typeof o=="number"&&(s.unicodes[o.toString(16)]={prefix:a,iconName:l}),s},{names:{},unicodes:{}});t_=r.names,n_=r.unicodes,Gc=Xo(Z.styleDefault,{family:Z.familyDefault})};KI(function(e){Gc=Xo(e.styleDefault,{family:Z.familyDefault})});s_();function qc(e,t){return(Zg[e]||{})[t]}function cP(e,t){return(e_[e]||{})[t]}function or(e,t){return(r_[e]||{})[t]}function i_(e){return t_[e]||{prefix:null,iconName:null}}function uP(e){var t=n_[e],n=qc("fas",e);return t||(n?{prefix:"fas",iconName:n}:null)||{prefix:null,iconName:null}}function Fn(){return Gc}var Xc=function(){return{prefix:null,iconName:null,rest:[]}};function Xo(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.family,r=n===void 0?$e:n,s=Ks[r][e],i=zs[r][e]||zs[r][s],o=e in Dt.styles?e:null;return i||o||null}var Jd=($i={},qe($i,$e,Object.keys(Gs[$e])),qe($i,Ve,Object.keys(Gs[Ve])),$i);function Jo(e){var t,n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.skipLookups,s=r===void 0?!1:r,i=(t={},qe(t,$e,"".concat(Z.cssPrefix,"-").concat($e)),qe(t,Ve,"".concat(Z.cssPrefix,"-").concat(Ve)),t),o=null,a=$e;(e.includes(i[$e])||e.some(function(u){return Jd[$e].includes(u)}))&&(a=$e),(e.includes(i[Ve])||e.some(function(u){return Jd[Ve].includes(u)}))&&(a=Ve);var l=e.reduce(function(u,c){var f=lP(Z.cssPrefix,c);if($r[c]?(c=iP[a].includes(c)?DI[a][c]:c,o=c,u.prefix=c):oP[a].indexOf(c)>-1?(o=c,u.prefix=Xo(c,{family:a})):f?u.iconName=f:c!==Z.replacementClass&&c!==i[$e]&&c!==i[Ve]&&u.rest.push(c),!s&&u.prefix&&u.iconName){var d=o==="fa"?i_(u.iconName):{},m=or(u.prefix,u.iconName);d.prefix&&(o=null),u.iconName=d.iconName||m||u.iconName,u.prefix=d.prefix||u.prefix,u.prefix==="far"&&!$r.far&&$r.fas&&!Z.autoFetchSvg&&(u.prefix="fas")}return u},Xc());return(e.includes("fa-bran Line truncated
`);n.setAttribute(_r,""),n.innerHTML=o}};function nm(e){e()}function c_(e,t){var n=typeof t=="function"?t:Gi;if(e.length===0)n();else{var r=nm;Z.mutateApproach===kI&&(r=Mn.requestAnimationFrame||nm),r(function(){var s=SP(),i=Qc.begin("mutate");e.map(s),i(),n()})}}var Zc=!1;function u_(){Zc=!0}function Ml(){Zc=!1}var ho=null;function rm(e){if(Kd&&Z.observeMutations){var t=e.treeCallback,n=t===void 0?Gi:t,r=e.nodeCallback,s=r===void 0?Gi:r,i=e.pseudoElementsCallback,o=i===void 0?Gi:i,a=e.observeMutationsRoot,l=a===void 0?Me:a;ho=new Kd(function(u){if(!Zc){var c=Fn();ds(u).forEach(function(f){if(f.type==="childList"&&f.addedNodes.length>0&&!tm(f.addedNodes[0])&&(Z.searchPseudoElements&&o(f.target),n(f.target)),f.type==="attributes"&&f.target.parentNode&&Z.searchPseudoElements&&o(f.target.parentNode),f.type==="attributes"&&tm(f.target)&&~HI.indexOf(f.attributeName))if(f.attributeName==="class"&&TP(f.target)){var d=Jo(Kc(f.target)),m=d.prefix,h=d.iconName;f.target.setAttribute(Bc,m||c),h&&f.target.setAttribute(Wc,h)}else OP(f.target)&&s(f.target)})}}),pn&&ho.observe(l,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}}function IP(){ho&&ho.disconnect()}function PP(e){var t=e.getAttribute("style"),n=[];return t&&(n=t.split(";").reduce(function(r,s){var i=s.split(":"),o=i[0],a=i.slice(1);return o&&a.length>0&&(r[o]=a.join(":").trim()),r},{})),n}function RP(e){var t=e.getAttribute("data-prefix"),n=e.getAttribute("data-icon"),r=e.innerText!==void 0?e.innerText.trim():"",s=Jo(Kc(e));return s.prefix||(s.prefix=Fn()),t&&n&&(s.prefix=t,s.iconName=n),s.iconName&&s.prefix||(s.prefix&&r.length>0&&(s.iconName=cP(s.prefix,e.innerText)||qc(s.prefix,Il(e.innerText))),!s.iconName&&Z.autoFetchSvg&&e.firstChild&&e.firstChild.nodeType===Node.TEXT_NODE&&(s.iconName=e.firstChild.data)),s}function xP(e){var t=ds(e.attributes).reduce(function(s,i){return s.name!=="class"&&s.name!=="style"&&(s[i.name]=i.value),s},{}),n=e.getAttribute("title"),r=e.getAttribute("data-fa-title-id");return Z.autoA11y&&(n?t["aria-labelledby"]="".concat(Z.replacementClass,"-title-").concat(r||Xs()):(t["aria-hidden"]="true",t.focusable="false")),t}function kP(){return{iconName:null,title:null,titleId:null,prefix:null,transform:zt,symbol:!1,mask:{iconName:null,prefix:null,rest:[]},maskId:null,extra:{classes:[],styles:{},attributes:{}}}}function sm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{styleParser:!0},n=RP(e),r=n.iconName,s=n.prefix,i=n.rest,o=xP(e),a=Rl("parseNodeAttributes",{},e),l=t.styleParser?PP(e):[];return X({iconName:r,title:e.getAttribute("title"),titleId:e.getAttribute("data-fa-title-id"),prefix:s,transform:zt,mask:{iconName:null,prefix:null,rest:[]},maskId:null,symbol:!1,extra:{classes:i,styles:l,attributes:o}},a)}var $P=Dt.styles;function f_(e){var t=Z.autoReplaceSvg==="nest"?sm(e,{styleParser:!1}):sm(e);return~t.extra.classes.indexOf(zg)?dn("generateLayersText",e,t):dn("generateSvgReplacementMutation",e,t)}var jn=new Set;Yc.map(function(e){jn.add("fa-".concat(e))});Object.keys(Ks[$e]).map(jn.add.bind(jn));Object.keys(Ks[Ve]).map(jn.add.bind(jn));jn=li(jn);function im(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;if(!pn)return Promise.resolve();var n=Me.documentElement.classList,r=function(f){return n.add("".concat(zd,"-").concat(f))},s=function(f){return n.remove("".concat(zd,"-").concat(f))},i=Z.autoFetchSvg?jn:Yc.map(function(c){return"fa-".concat(c)}).concat(Object.keys($P));i.includes("fa")||i.push("fa");var o=[".".concat(zg,":not([").concat(_r,"])")].concat(i.map(function(c){return".".concat(c,":not([").concat(_r,"])")})).join(", ");if(o.length===0)return Promise.resolve();var a=[];try{a=ds(e.querySelectorAll(o))}catch{}if(a.length>0)r("pending"),s("complete");else return Promise.resolve();var l=Qc.begin("onTree"),u=a.reduce(function(c,f){try{var d=f_(f);d&&c.push(d)}catch(m){Kg||m.name==="MissingIcon"&&console.error(m)}return c},[]);return new Promise(function(c,f){Promise.all(u).then(function(d){c_(d,function(){r("active"),r("complete"),s("pending"),typeof t=="function"&&t(),l(),c()})}).catch(function(d){l(),f(d)})})}function DP(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;f_(e).then(function(n){n&&c_([n],t)})}function MP(e){return function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=(t||{}).icon?t:xl(t||{}),s=n.mask;return s&&(s=(s||{}).icon?s:xl(s||{})),e(r,X(X({},n),{},{mask:s}))}}var FP=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.transform,s=r===void 0?zt:r,i=n.symbol,o=i===void 0?!1:i,a=n.mask,l=a===void 0?null:a,u=n.maskId,c=u===void 0?null:u,f=n.title,d=f===void 0?null:f,m=n.titleId,h=m===void 0?null:m,y=n.classes,v=y===void 0?[]:y,w=n.attributes,O=w===void 0?{}:w,E=n.styles,A=E===void 0?{}:E;if(t){var C=t.prefix,S=t.iconName,I=t.icon;return Qo(X({type:"icon"},t),function(){return vr("beforeDOMElementCreation",{iconDefinition:t,params:n}),Z.autoA11y&&(d?O["aria-labelledby"]="".concat(Z.replacem Line truncated
`),e.removeAttribute(n),r()}).catch(s)}else r()}else r()})}function YP(e){return Promise.all([am(e,"::before"),am(e,"::after")])}function KP(e){return e.parentNode!==document.head&&!~$I.indexOf(e.tagName.toUpperCase())&&!e.getAttribute(Ll)&&(!e.parentNode||e.parentNode.tagName!=="svg")}function lm(e){if(pn)return new Promise(function(t,n){var r=ds(e.querySelectorAll("*")).filter(KP).map(YP),s=Qc.begin("searchPseudoElements");u_(),Promise.all(r).then(function(){s(),Ml(),t()}).catch(function(){s(),Ml(),n()})})}var zP={hooks:function(){return{mutationObserverCallbacks:function(n){return n.pseudoElementsCallback=lm,n}}},provides:function(t){t.pseudoElements2svg=function(n){var r=n.node,s=r===void 0?Me:r;Z.searchPseudoElements&&lm(s)}}},cm=!1,GP={mixout:function(){return{dom:{unwatch:function(){u_(),cm=!0}}}},hooks:function(){return{bootstrap:function(){rm(Rl("mutationObserverCallbacks",{}))},noAuto:function(){IP()},watch:function(n){var r=n.observeMutationsRoot;cm?Ml():rm(Rl("mutationObserverCallbacks",{observeMutationsRoot:r}))}}}},um=function(t){var n={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return t.toLowerCase().split(" ").reduce(function(r,s){var i=s.toLowerCase().split("-"),o=i[0],a=i.slice(1).join("-");if(o&&a==="h")return r.flipX=!0,r;if(o&&a==="v")return r.flipY=!0,r;if(a=parseFloat(a),isNaN(a))return r;switch(o){case"grow":r.size=r.size+a;break;case"shrink":r.size=r.size-a;break;case"left":r.x=r.x-a;break;case"right":r.x=r.x+a;break;case"up":r.y=r.y-a;break;case"down":r.y=r.y+a;break;case"rotate":r.rotate=r.rotate+a;break}return r},n)},qP={mixout:function(){return{parse:{transform:function(n){return um(n)}}}},hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-transform");return s&&(n.transform=um(s)),n}}},provides:function(t){t.generateAbstractTransformGrouping=function(n){var r=n.main,s=n.transform,i=n.containerWidth,o=n.iconWidth,a={transform:"translate(".concat(i/2," 256)")},l="translate(".concat(s.x*32,", ").concat(s.y*32,") "),u="scale(".concat(s.size/16*(s.flipX?-1:1),", ").concat(s.size/16*(s.flipY?-1:1),") "),c="rotate(".concat(s.rotate," 0 0)"),f={transform:"".concat(l," ").concat(u," ").concat(c)},d={transform:"translate(".concat(o/2*-1," -256)")},m={outer:a,inner:f,path:d};return{tag:"g",attributes:X({},m.outer),children:[{tag:"g",attributes:X({},m.inner),children:[{tag:r.icon.tag,children:r.icon.children,attributes:X(X({},r.icon.attributes),m.path)}]}]}}}},Ma={x:0,y:0,width:"100%",height:"100%"};function fm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return e.attributes&&(e.attributes.fill||t)&&(e.attributes.fill="black"),e}function XP(e){return e.tag==="g"?e.children:[e]}var JP={hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-mask"),i=s?Jo(s.split(" ").map(function(o){return o.trim()})):Xc();return i.prefix||(i.prefix=Fn()),n.mask=i,n.maskId=r.getAttribute("data-fa-mask-id"),n}}},provides:function(t){t.generateAbstractMask=function(n){var r=n.children,s=n.attributes,i=n.main,o=n.mask,a=n.maskId,l=n.transform,u=i.width,c=i.icon,f=o.width,d=o.icon,m=XI({transform:l,containerWidth:f,iconWidth:u}),h={tag:"rect",attributes:X(X({},Ma),{},{fill:"white"})},y=c.children?{children:c.children.map(fm)}:{},v={tag:"g",attributes:X({},m.inner),children:[fm(X({tag:c.tag,attributes:X(X({},c.attributes),m.path)},y))]},w={tag:"g",attributes:X({},m.outer),children:[v]},O="mask-".concat(a||Xs()),E="clip-".concat(a||Xs()),A={tag:"mask",attributes:X(X({},Ma),{},{id:O,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[h,w]},C={tag:"defs",children:[{tag:"clipPath",attributes:{id:E},children:XP(d)},A]};return r.push(C,{tag:"rect",attributes:X({fill:"currentColor","clip-path":"url(#".concat(E,")"),mask:"url(#".concat(O,")")},Ma)}),{children:r,attributes:s}}}},QP={provides:function(t){var n=!1;Mn.matchMedia&&(n=Mn.matchMedia("(prefers-reduced-motion: reduce)").matches),t.missingIconAbstract=function(){var r=[],s={fill:"currentColor"},i={attributeType:"XML",repeatCount:"indefinite",dur:"2s"};r.push({tag:"path",attributes:X(X({},s),{},{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66 Line truncated
+2 -2
View File
@@ -5,8 +5,8 @@
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title> <title>Vite App</title>
<script type="module" crossorigin src="/assets/index-VvMfePyX.js"></script> <script type="module" crossorigin src="/assets/index-B_AXNEWQ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-21nzev1V.css"> <link rel="stylesheet" crossorigin href="/assets/index-B5vQMdQB.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
-14
View File
@@ -1,14 +0,0 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript'
],
parserOptions: {
ecmaVersion: 'latest'
}
}
+2
View File
@@ -0,0 +1,2 @@
VITE_API_BASE_URL=/api
#VITE_API_BASE_URL=http://localhost:8008/api
+3
View File
@@ -0,0 +1,3 @@
{
"singleQuote": true
}
+24
View File
@@ -0,0 +1,24 @@
import { defineConfig } from "eslint/config";
import { js } from "@eslint/js";
import { FlagCompat } from "eslint/eslintrc";
import pluginVue from "eslint-plugin-vue";
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default defineConfig([{
...pluginVue.configs['flat/essential'],
extends: compat.extends(
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-typescript",
),
languageOptions: {
ecmaVersion: "latest",
parserOptions: {},
},
}]);
+3426 -3389
View File
File diff suppressed because it is too large. Load diff
+30 -31
View File
@@ -13,38 +13,37 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/fontawesome-svg-core": "~7.2.0",
"@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/free-solid-svg-icons": "~7.2.0",
"@fortawesome/vue-fontawesome": "^3.0.8", "@fortawesome/vue-fontawesome": "~3.1.3",
"@popperjs/core": "^2.11.8", "@stomp/stompjs": "~7.3.0",
"@vuelidate/core": "^2.0.3", "@vuelidate/core": "~2.0.3",
"@vuelidate/validators": "^2.0.4", "@vuelidate/validators": "~2.0.4",
"axios": "^1.7.2", "@vueuse/core": "~14.2.1",
"bootstrap": "^5.3.3", "axios": "~1.13.6",
"pinia": "^2.1.7", "bootstrap": "~5.3.8",
"vue": "^3.4.21", "pinia": "~3.0.4",
"vue-i18n": "^9.13.1", "vue": "~3.5.30",
"vue-router": "^4.3.0" "vue-draggable-plus": "~0.6.1",
"vue-i18n": "~11.3.0",
"vue-router": "~5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.8.0", "@eslint/js": "~10.0.1",
"@tsconfig/node20": "^20.1.4", "@intlify/eslint-plugin-vue-i18n": "~4.3.0",
"@types/bootstrap": "^5.2.10", "@tsconfig/node24": "~24.0.4",
"@types/jsdom": "^21.1.6", "@types/bootstrap": "~5.2.10",
"@types/node": "^20.12.5", "@types/node": "~25.5.0",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "~6.0.5",
"@vue/eslint-config-typescript": "^13.0.0", "@vue/eslint-config-typescript": "~14.7.0",
"@vue/test-utils": "^2.4.5", "@vue/test-utils": "~2.4.6",
"@vue/tsconfig": "^0.5.1", "@vue/tsconfig": "~0.9.0",
"eslint": "^8.57.0", "eslint": "~10.0.3",
"eslint-plugin-vue": "^9.23.0", "eslint-plugin-vue": "~10.8.0",
"jsdom": "^24.0.0", "sass": "~1.98.0",
"npm-run-all2": "^6.1.2", "typescript": "~5.9.3",
"sass": "^1.77.6", "vite": "~8.0.0",
"typescript": "~5.4.0", "vite-plugin-vue-devtools": "~8.1.0",
"vite": "^5.2.8", "vitest": "~4.1.0"
"vite-plugin-vue-devtools": "^7.0.25",
"vitest": "^1.4.0",
"vue-tsc": "^2.0.11"
} }
} }
+14 -11
View File
@@ -2,7 +2,7 @@
import { provide, ref } from 'vue'; import { provide, ref } from 'vue';
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
import { infoModalShowFnKey } from './services/UtilService'; import { infoModalShowFnKey, navbarKey } from './services/UtilService';
import NavBar from '@/components/blocks/NavBar.vue'; import NavBar from '@/components/blocks/NavBar.vue';
import GenericInfoModal from '@/components/modals/GenericInfoModal.vue'; import GenericInfoModal from '@/components/modals/GenericInfoModal.vue';
@@ -10,31 +10,34 @@ import { useUserStore } from './stores/UserStore';
const userStore = useUserStore(); const userStore = useUserStore();
const userLoading = ref( true ); const userLoading = ref(true);
userStore.userCheckPromise userStore.userCheckPromise.finally(() => {
.finally( () => {
userLoading.value = false; userLoading.value = false;
} ); });
const infoModal = ref<InstanceType<typeof GenericInfoModal> | null>( null ); const infoModal = ref<InstanceType<typeof GenericInfoModal> | null>(null);
function showInfoModal( title: string, text: string ): void { function showInfoModal(title: string, text: string): void {
if( infoModal.value ) { if (infoModal.value) {
infoModal.value.modalTitle = title; infoModal.value.modalTitle = title;
infoModal.value.modalText = text; infoModal.value.modalText = text;
infoModal.value.show(); infoModal.value.show();
} else { } else {
console.error( 'Modal not yet available' ); console.error('Modal not yet available');
} }
} }
provide( infoModalShowFnKey, showInfoModal ); provide(infoModalShowFnKey, showInfoModal);
const navbar = ref<InstanceType<typeof NavBar> | undefined>(undefined);
provide(navbarKey, navbar);
userStore.initialHistoryLen = window.history.length;
</script> </script>
<template> <template>
<div class="vh-100 overflow-y-scroll overflow-x-hidden"> <div class="vh-100 overflow-y-scroll overflow-x-hidden">
<NavBar :userLoading="userLoading" /> <NavBar ref="navbar" :userLoading="userLoading" />
<RouterView /> <RouterView />
+19
View File
@@ -5,3 +5,22 @@
.pointer { .pointer {
cursor: pointer; cursor: pointer;
} }
.cursor-move{
cursor: move;
}
.spinny-spin{
animation-name: spinny;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes spinny {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

@@ -46,11 +46,16 @@ $body-secondary-bg: $light-accented;
$dropdown-link-hover-bg: $dark-accented; $dropdown-link-hover-bg: $dark-accented;
$modal-fade-transform: scale(.75); $modal-fade-transform: scale(.75);
$breadcrumb-divider: quote(">");
$border-radius: 0;
// 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets) // 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets)
@import "bootstrap/scss/variables"; @import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark"; @import "bootstrap/scss/variables-dark";
$form-file-button-bg: var(--#{$prefix}secondary-bg);
$form-file-button-hover-bg: var(--#{$prefix}tertiary-bg);
/* Bootstrap Color Map adjustments */ /* Bootstrap Color Map adjustments */
$custom-colors: ( $custom-colors: (
@@ -89,6 +94,36 @@ $utilities: map-merge(
), ),
), ),
), ),
"rounded-bottom-end": (
property: border-bottom-right-radius,
class: rounded-bottom-end,
values: (
null: var(--#{$prefix}border-radius),
0: 0,
1: var(--#{$prefix}border-radius-sm),
2: var(--#{$prefix}border-radius),
3: var(--#{$prefix}border-radius-lg),
4: var(--#{$prefix}border-radius-xl),
5: var(--#{$prefix}border-radius-xxl),
circle: 50%,
pill: var(--#{$prefix}border-radius-pill)
)
),
"rounded-top-end": (
property: border-top-right-radius,
class: rounded-top-end,
values: (
null: var(--#{$prefix}border-radius),
0: 0,
1: var(--#{$prefix}border-radius-sm),
2: var(--#{$prefix}border-radius),
3: var(--#{$prefix}border-radius-lg),
4: var(--#{$prefix}border-radius-xl),
5: var(--#{$prefix}border-radius-xxl),
circle: 50%,
pill: var(--#{$prefix}border-radius-pill)
)
),
), ),
); );
@@ -100,3 +135,24 @@ $utilities: map-merge(
@import "./exotic_theme.scss"; @import "./exotic_theme.scss";
@import "../css/main.css"; @import "../css/main.css";
@mixin animate($animation,$duration,$function,$times,$direction){
animation-name: $animation;
animation-duration: $duration;
animation-iteration-count: $times;
animation-timing-function: $function;
animation-direction: $direction;
}
@mixin keyframes($name){
@keyframes #{$name}{
@content;
}
}
.bg-pulse-primary{
@include keyframes(pulse){
to {
background-color: $primary;
}
}
@include animate(pulse, .75s, ease, infinite, alternate-reverse);
}
@@ -0,0 +1,198 @@
<script setup lang="ts">
import { AnswerType } from '@/models/board/AnswerType';
import type { BoardEntry } from '@/models/board/BoardEntry';
import { QuestionType } from '@/models/board/QuestionType';
import { computed, ref } from 'vue';
const props = defineProps<{
boardEntry: BoardEntry,
selectedQuestionIndex: number,
isAnswerShown: boolean,
isQuestionShown: boolean,
categoryName: string,
}>();
const emit = defineEmits<{
questionSelected: [questionIndex: number],
showQuestion: [],
hideQuestion: [],
showAnswer: [],
hideAnswer: [],
showBoard: [],
}>();
const question = computed( () => {
return props.boardEntry.questions[props.selectedQuestionIndex ?? 0];
});
function selectQuestionIndex( qIndex: number ) {
emit( "questionSelected", qIndex );
}
function showQuestion(){
emit("showQuestion");
}
function hideQuestion(){
emit("hideQuestion");
}
function showAnswer(){
emit("showAnswer");
}
function hideAnswer(){
emit("hideAnswer");
}
function backToBoard(){
emit("showBoard");
}
const audio = ref<HTMLAudioElement | null>(null);
function startAudio(){
if( audio.value ){
audio.value.play();
} else {
audio.value = new Audio(question.value.audio);
audio.value.play();
}
}
function stopAudio(){
if( audio.value ){
audio.value.pause();
}
}
</script>
<template>
<div class="h-100 d-flex flex-column">
<div class="row h-100">
<div class="col h-100 mx-3 overflow-y-auto">
<div class="ratio ratio-16x9">
<div class="w-100 h-100 d-flex justify-content-center align-items-center">
<template v-if="isAnswerShown && boardEntry.answer.answerType === AnswerType.IMAGE">
<div class="h-75 w-100 d-flex justify-content-center align-items-center">
<img
v-if="boardEntry.answer.image"
:src="boardEntry.answer.image"
alt="User uploaded - No caption available"
class="h-100 w-100 object-contain"
>
</div>
</template>
<template v-else-if="isQuestionShown">
<span v-if="boardEntry.questions.length === 0" class="fs-1">
No Question to show
</span>
<span v-else-if="question.questionType === QuestionType.TEXT" class="text-center preserve-breaks" :style="`font-size: ${question.fontScaling}em`">
{{ question.text }}
</span>
<template v-else-if="question.questionType === QuestionType.IMAGE">
<div class="d-flex flex-column justify-content-center align-items-center h-100 w-100">
<span class="text-center preserve-breaks" :style="`font-size: ${question.fontScaling}em`">
{{ question.text }}
</span>
<div class="h-75 w-100 d-flex justify-content-center align-items-center">
<img
v-if="question.image"
:src="question.image"
alt="User uploaded - No caption available"
class="h-100 w-100 object-contain"
>
</div>
</div>
</template>
<template v-else-if="question.questionType === QuestionType.AUDIO">
<div class="d-flex flex-column justify-content-center align-items-center h-100 w-100">
<span class="text-center preserve-breaks" :style="`font-size: ${question.fontScaling}em`">
{{ question.text }}
</span>
<div class="h-75 w-100 d-flex justify-content-center align-items-center">
<img
v-if="question.audio"
src="/src/assets/images/SoundWave.png"
alt="User uploaded - No caption available"
class="h-100 w-100 object-contain"
>
<button class="btn btn-primary" @click="startAudio">
Play Audio
</button>
<button class="btn btn-primary" @click="stopAudio">
Stop Audio
</button>
</div>
</div>
</template>
</template>
<!-- Category Name -->
<div class="position-absolute top-0 start-0">
<span class="fs-2">
{{ }}
</span>
</div>
<!-- Points -->
<div class="position-absolute bottom-0 end-0">
<span class="fs-2">
{{ boardEntry.points }}
</span>
</div>
<!-- title -->
<div class="position-absolute top-0 start-50 translate-middle-x">
<span class="fs-2">
{{ boardEntry.name }}
</span>
</div>
<!-- Back to Board -->
<div class="position-absolute top-0 start-0">
<div>
<button class="btn btn-outline-primary mt-2" @click="backToBoard">
Back to Board
</button>
</div>
</div>
<!-- Back to Board -->
<div class="position-absolute top-0 end-0">
<div class="mt-2">
<button v-if="props.isQuestionShown" class="btn btn-outline-primary me-3" @click="hideQuestion">
Hide Question
</button>
<button v-else class="btn btn-outline-primary me-3" @click="showQuestion">
Show Question
</button>
<button v-if="props.isAnswerShown" class="btn btn-outline-primary" @click="hideAnswer">
Hide Answer
</button>
<button v-else class="btn btn-outline-primary" @click="showAnswer">
Show Answer
</button>
</div>
</div>
<!-- Answer text -->
<div v-if="isAnswerShown" class="position-absolute bottom-0 start-50 translate-middle-x mb-2">
<div class="bg-primary p-2 rounded fs-4 text-center">
Answer:<br>{{ boardEntry.answer.text }}
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if=" props.boardEntry.questions.length > 1 " class="position-absolute bottom-0 start-0 mb-3 ms-3">
<template v-for="( question, questionIndex) in props.boardEntry.questions" :key="question.id">
<button class="btn me-2"
:class="[
{ 'btn-primary': props.selectedQuestionIndex === questionIndex },
{ 'btn-outline-primary': props.selectedQuestionIndex !== questionIndex }
]"
:disabled="props.selectedQuestionIndex === questionIndex"
@click="selectQuestionIndex( questionIndex )">
{{ questionIndex + 1 }}
</button>
</template>
</div>
</div>
</template>
<style lang="css" scoped>
.object-contain{
object-fit: contain;
}
</style>
@@ -1,39 +1,80 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { useRouter } from 'vue-router';
import type { Board } from '@/models/board/Board';
import { userService } from '@/services/UserService';
import IconJeobeardy from '../icons/IconJeobeardy.vue';
const boards = ref([{ const props = defineProps<{
id: 1, withNewOption: boolean;
boardName: "mockBoard", }>();
},{
id: 2, const router = useRouter();
boardName: "test Mock",
},{ const boards = ref<Array<Board>>([]);
id: 3,
boardName: "Mocka Board", function editBoard(board: Board) {
},{ router.push({
id: 4, name: 'create',
boardName: "Mocka Board 2", params: {
}]); boardId: board.id,
},
});
}
function createNewBoard() {
if (props.withNewOption) {
router.push({ name: 'create' });
}
}
const boardsLoading = ref(true);
userService
.getBoardsForUser()
.then((loadedBoards) => {
boards.value = loadedBoards;
})
.catch((error) => {
console.error(error);
})
.finally(() => {
boardsLoading.value = false;
});
</script> </script>
<template> <template>
<div class="row"> <div class="row">
<template v-if="boardsLoading">
<div class="col-12 d-flex justify-content-center py-3">
<IconJeobeardy class="spinny-spin spinny-size" />
</div>
</template>
<template v-else>
<template v-for="board in boards" :key="board.id"> <template v-for="board in boards" :key="board.id">
<div class="col-4 mb-3"> <div class="col-4 mb-3">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header position-relative">
{{ board.boardName }} {{ board.boardName }}
<button
class="d-hover position-absolute top-50 translate-middle-y end-0 me-1 btn btn-sm btn-outline-danger"
>
<!-- TODO -->
<FontAwesomeIcon :icon="['fas', 'trash']" />
</button>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="d-flex justify-content-around align-items-center"> <div class="d-flex justify-content-around align-items-center">
<button class="btn btn-sm btn-primary"> <button
class="btn btn-sm btn-primary"
@click="editBoard(board)"
>
<FontAwesomeIcon :icon="['fas', 'edit']" /> <FontAwesomeIcon :icon="['fas', 'edit']" />
Edit Edit
</button> </button>
<button class="btn btn-sm btn-primary"> <button class="btn btn-sm btn-primary">
<!-- TODO -->
<FontAwesomeIcon :icon="['fas', 'play']" /> <FontAwesomeIcon :icon="['fas', 'play']" />
Play Play
</button> </button>
@@ -44,5 +85,31 @@ const boards = ref([{
</div> </div>
</div> </div>
</template> </template>
<div v-if="props.withNewOption" class="col-4 mb-3">
<button
class="btn btn-outline-primary w-100 h-100 d-flex flex-column justify-content-center align-items-center gap-2"
@click="createNewBoard"
>
Create new Board
<FontAwesomeIcon :icon="['fas', 'plus']" size="2x" />
</button>
</div>
</template>
</div> </div>
</template> </template>
<style scoped>
.spinny-size {
max-width: 6.66em;
max-height: 6.66em;
}
.d-hover {
display: initial;
opacity: 0%;
transition: opacity ease 0.33s;
}
div:hover > div > .d-hover {
opacity: 100%;
display: initial;
}
</style>
@@ -0,0 +1,73 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const props = defineProps<{
board: Board,
}>();
const emit = defineEmits<{
categorySelected: [index: number],
boardEntrySelected: [cIndex: number, bEIndex: number],
}>();
function categorySelected(cIndex: number){
emit("categorySelected", cIndex);
}
function boardEntrySelected(cIndex: number, bEIndex: number){
emit("boardEntrySelected", cIndex, bEIndex);
}
</script>
<template>
<div class="mx-3 h-100 d-flex flex-column">
<div class="row">
<div class="col text-center p-3">
<h2>
{{ board.boardName }}
</h2>
</div>
</div>
<div class="row h-100">
<template v-for="(category, categoryIndex) in props.board.categories " :key="category.name">
<div class="col pb-2">
<div class="d-flex flex-column h-100">
<button
class="flex-fill board-card-max-height card bg-primary w-100 my-1"
@click="categorySelected(categoryIndex)"
:title="board.categories[categoryIndex].description"
:style="[board.categories[categoryIndex].customColor ? {'background-color': `${board.categories[categoryIndex].color} !important`} : {}]"
>
<div class="card-body d-flex align-items-center justify-content-center">
{{ category.name }}
</div>
</button>
<template v-for=" (boardEntry, boardEntryIndex) in category.boardEntries " :key="boardEntry.name">
<button class="flex-fill board-card-max-height card bg-body-secondary w-100 my-1" @click="boardEntrySelected(categoryIndex, boardEntryIndex)">
<div class="card-body d-flex align-items-center justify-content-center">
<template v-if="board.pointsAreTitle">
{{ boardEntry.points }}
</template>
<template v-else>
{{ boardEntry.name }}
</template>
</div>
</button>
</template>
</div>
</div>
</template>
</div>
</div>
</template>
<style lang="css" scoped>
.board-card-max-height{
max-height: 20%;
}
</style>
@@ -0,0 +1,77 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import EditCategoryPanel from '@/components/blocks/EditCategoryPanel.vue';
import EditBoardPanel from '@/components/blocks/EditBoardPanel.vue';
import EditBoardEntryPanel from '@/components/blocks/EditBoardEntryPanel.vue';
import EditQuestionPanel from './EditQuestionPanel.vue';
const props = defineProps<{
categoryIndex: number | null,
boardEntryIndex: number | null,
questionIndex: number | null,
}>()
const emit = defineEmits<{
editBoard: [],
editCategory: [cIndex: number],
editBoardEntry: [cIndex: number, bEIndex: number],
editQuestion: [cIndex: number, bEIndex: number, qIndex: number],
}>()
const board = defineModel<Board>( { required: true } );
function editBoard(){
emit("editBoard");
}
function editCategory(cIndex: number){
emit("editCategory", cIndex);
}
function editBoardEntry(cIndex: number, bEIndex: number){
emit("editBoardEntry", cIndex, bEIndex);
}
function editQuestion(cIndex: number, bEIndex: number, qIndex: number){
emit("editQuestion", cIndex, bEIndex, qIndex);
}
</script>
<template>
<div>
<EditBoardPanel
v-if="props.categoryIndex === null && props.boardEntryIndex === null && props.questionIndex === null"
v-model="board"
@editCategory="editCategory"
/>
<EditCategoryPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex === null && props.questionIndex === null"
v-model="board"
:categoryIndex="props.categoryIndex"
@editBoard="editBoard"
@editBoardEntry="editBoardEntry"
/>
<EditBoardEntryPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex !== null && props.questionIndex === null"
v-model="board" :categoryIndex="props.categoryIndex"
:boardEntryIndex="props.boardEntryIndex"
@editQuestion="editQuestion"
@editCategory="editCategory"
@editBoard="editBoard"
/>
<EditQuestionPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex !== null && props.questionIndex !== null"
v-model="board"
:categoryIndex="props.categoryIndex"
:boardEntryIndex="props.boardEntryIndex"
:questionIndex="props.questionIndex"
@editBoardEntry="editBoardEntry"
@editCategory="editCategory"
@editBoard="editBoard"
/>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>
@@ -0,0 +1,225 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { VueDraggable } from 'vue-draggable-plus';
import type { Board } from '@/models/board/Board';
import { Question } from '@/models/board/Question';
import { QuestionType, type QuestionTypeType } from '@/models/board/QuestionType';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { AnswerType } from '@/models/board/AnswerType';
const { t } = useI18n();
const board = defineModel<Board>( { required: true } );
const props = defineProps<{
categoryIndex: number,
boardEntryIndex: number,
}>();
const emit = defineEmits<{
editBoard: [],
editCategory: [categoryIndex: number],
editQuestion: [categoryIndex: number, boardEntryIndex: number, questionIndex: number],
}>()
const boardEntry = computed( () => {
return board.value.categories[props.categoryIndex].boardEntries[props.boardEntryIndex];
});
const newQuestionText = ref( '' );
const newQuestionType = ref<QuestionTypeType>(QuestionType.TEXT);
function addQuestion() {
if( boardEntry.value.questions.length >= 10) {
return;
}
const newQuestion = new Question(newQuestionText.value, newQuestionType.value);
boardEntry.value.questions.push( newQuestion );
}
function deleteQuestion( index: number ) {
boardEntry.value.questions.splice( index, 1 );
}
function moveQuestionUp( index: number ) {
if( index === 0 || boardEntry.value.questions.length <= 1 ) {
return;
}
const tmp = boardEntry.value.questions[index];
boardEntry.value.questions[index] = boardEntry.value.questions[index - 1];
boardEntry.value.questions[index - 1] = tmp;
}
function moveQuestionDown( index: number ) {
if( index === boardEntry.value.questions.length - 1 || boardEntry.value.questions.length <= 1 ) {
return;
}
const tmp = boardEntry.value.questions[index];
boardEntry.value.questions[index] = boardEntry.value.questions[index + 1];
boardEntry.value.questions[index + 1] = tmp;
}
function newImageUploaded( event: Event ) {
const element = event.currentTarget as HTMLInputElement;
let files = element.files;
if( files === null || files.length === 0 ) {
return;
}
boardEntry.value.answer.image = URL.createObjectURL(files[0]);
}
function openBoard() {
emit("editBoard");
}
function openCategory(categoryIndex: number) {
emit("editCategory", categoryIndex);
}
function openQuestion(categoryIndex: number, boardEntryIndex: number, questionIndex: number) {
emit("editQuestion", categoryIndex, boardEntryIndex, questionIndex);
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 px-2">
<div class="row">
<div class="col">
<div class="d-flex align-items-center mb-2 overflow-x-auto pb-2">
<button class="btn btn-sm btn-outline-primary" :title="t('common.back')" @click="openCategory(props.categoryIndex)">
<FontAwesomeIcon :icon="['fas', 'angle-left']"/>
</button>
<nav class="flex-grow-1 ms-2" aria-label="breadcrumb">
<ol class="breadcrumb mb-0 flex-nowrap">
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openBoard">
{{ board.boardName }}
</a>
</li>
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openCategory( props.categoryIndex )">
{{ board.categories[props.categoryIndex].name }}
</a>
</li>
<li class="breadcrumb-item active text-truncate" aria-current="page">
{{ boardEntry.name }}
</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="d-flex border-bottom border-3 border-primary align-items-center mb-2">
<h2 class="flex-grow-1 ms-2">{{ t( "board.boardentry.infos" ) }}</h2>
</div>
<label for="category-name">{{ t( 'board.boardentry.name' ) }}</label>
<input type="text" id="category-name" class="form-control mb-2" v-model="boardEntry.name" :placeholder="t( 'board.boardentry.name' )">
<label for="board-entry-points">{{ t( 'board.boardentry.points' ) }}</label>
<input type="number" id="board-entry-points" class="form-control" v-model="boardEntry.points" :placeholder="t( 'board.boardentry.points' )">
</div>
</div>
<div class="row mt-3">
<div class="col">
<h4>{{ t( "board.question.label", 2 ) }}</h4>
<template v-if=" boardEntry.questions.length === 0 ">
<p>
{{ t( "board.question.label", 0 ) }}
</p>
</template>
<template v-else>
<VueDraggable v-model="board.categories[props.categoryIndex].boardEntries" item-key="id" :animation="150" ghost-class="draggable-ghost"
tag="ul" class="list-group" handle=".drag-handle">
<template v-for="(question, questionIndex) of boardEntry.questions" :key="question.id">
<li class="list-group-item bg-body-secondary p-0">
<div class="d-flex justify-content-between w-100">
<div class="flex-grow-1 d-flex align-items-center text-truncate">
<div
class="drag-handle h-100 d-flex justify-content-center align-items-center cursor-move border-end border-1 bg-primary bg-opacity-10">
<FontAwesomeIcon :icon="['fas', 'grip-lines']" class="px-2" />
</div>
<div class="text-truncate">
<span class="ms-2">
<FontAwesomeIcon v-if="question.questionType === QuestionType.TEXT" :icon="['fas', 'align-center']" />
<span class="fw-light">
({{ question.text.length === 0 ? 'No Text yet' : question.text }})
</span>
</span>
</div>
</div>
<div class="d-flex">
<button class="btn btn-primary rounded-0" @click="openQuestion( props.categoryIndex, props.boardEntryIndex, questionIndex )">
<FontAwesomeIcon :icon="['fas', 'edit']" size="sm" />
</button>
<div class="d-flex flex-column justify-content-center align-items-center h-100" role="group"
aria-label="Vertical button group">
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveQuestionUp( questionIndex )"
:disabled="questionIndex === 0">
<FontAwesomeIcon :icon="['fas', 'angle-up']" size="xs" />
</button>
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveQuestionDown( questionIndex )"
:disabled="questionIndex === boardEntry.questions.length - 1">
<FontAwesomeIcon :icon="['fas', 'angle-down']" size="xs" />
</button>
</div>
<button class="btn btn-danger rounded-start-0 rounded-0"
:class="[{ 'rounded-bottom-end': questionIndex === boardEntry.questions.length - 1 }, { 'rounded-top-end': questionIndex === 0 }]"
@click="deleteQuestion( questionIndex )">
<FontAwesomeIcon :icon="['fas', 'trash']" size="sm" />
</button>
</div>
</div>
</li>
</template>
</VueDraggable>
</template>
<label class="mt-2" for="type-for-new-question">{{ t( "board.question.add" ) }}</label>
<div class="row mb-2">
<div class="col">
<select id="type-for-new-question" v-model="newQuestionType" class="form-select">
<template v-for="questionType in QuestionType" :key="questionType">
<option :value="questionType" :title="t(`board.question.types.description.${questionType}`)">{{ t(`board.question.types.title.${questionType}`) }}</option>
</template>
</select>
</div>
<div class="col-auto">
<button class="btn btn-primary" @click="addQuestion">
<FontAwesomeIcon :icon="['fas', 'plus']" />
</button>
</div>
</div>
<div class="row">
<div class="col">
<h4>{{ t('board.answer.label', 2) }}</h4>
<label class="mt-2" for="type-for-answer">{{ t( "board.answer.types.label" ) }}</label>
<select id="type-for-answer" v-model="boardEntry.answer.answerType" class="form-select">
<template v-for="answerType in AnswerType" :key="answerType">
<option :value="answerType" :title="t(`board.answer.types.description.${answerType}`)">{{ t(`board.answer.types.title.${answerType}`) }}</option>
</template>
</select>
<label class="mt-2" for="answer-text">{{ t( 'board.answer.text' ) }}</label>
<textarea id="answer-text" v-model="boardEntry.answer.text" class="form-control mb-2"
:placeholder="t( 'board.answer.text' )"></textarea>
<template v-if="boardEntry.answer.answerType === AnswerType.IMAGE">
<label for="answer-image-input">{{ t( 'board.question.upload.image' ) }}</label>
<input
id="answer-image-input"
type="file"
class="form-control mb-2"
@change="newImageUploaded"
accept="image/png, image/jpeg"
>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>
@@ -0,0 +1,130 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { Category } from '@/models/board/Category';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { VueDraggable } from 'vue-draggable-plus';
const { t } = useI18n();
const emit = defineEmits<{
editCategory: [index: number],
}>()
const board = defineModel<Board>( { required: true } );
const newCategoryName = ref( '' );
function addCategory() {
if( board.value.categories.length >= 12 ) {
return;
}
const newCategory = new Category( newCategoryName.value, '' );
board.value.categories.push( newCategory );
}
function deleteCategory( index: number ) {
board.value.categories.splice( index, 1 );
}
function moveCategoryUp( index: number ) {
if( index === 0 || board.value.categories.length <= 1 ) {
return;
}
const tmp = board.value.categories[index];
board.value.categories[index] = board.value.categories[index - 1];
board.value.categories[index - 1] = tmp;
}
function moveCategoryDown( index: number ) {
if( index === board.value.categories.length - 1 || board.value.categories.length <= 1 ) {
return;
}
const tmp = board.value.categories[index];
board.value.categories[index] = board.value.categories[index + 1];
board.value.categories[index + 1] = tmp;
}
function openCategory( index: number ) {
emit("editCategory", index);
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 p-2">
<div class="row">
<div class="col">
<h2 class="border-bottom border-3 border-primary">{{ t( "board.infos" ) }}</h2>
<label for="board-name">{{ t( 'board.name' ) }}</label>
<input type="text" id="board-name" class="form-control" v-model="board.boardName" :placeholder="t( 'board.name' )">
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="points-for-title" v-model="board.pointsAreTitle">
<label for="points-for-title" class="form-check-label">{{ t( 'board.options.pointsForTitle' ) }}</label>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col">
<h4>{{ t( "board.category.label", 2 ) }}</h4>
<template v-if=" board.categories.length === 0 ">
{{ t( "board.category.label", 0 ) }}
</template>
<template v-else>
<VueDraggable v-model="board.categories" item-key="id" :animation="150" ghost-class="draggable-ghost"
tag="ul" class="list-group" handle=".drag-handle">
<template v-for="( category, categoryIndex) of board.categories" :key="category.id">
<li class="list-group-item bg-body-secondary p-0">
<div class="d-flex justify-content-between w-100">
<div class="flex-grow-1 d-flex align-items-center g-3 justify-content-start">
<div
class="drag-handle h-100 d-flex justify-content-center align-items-center cursor-move border-end border-1 bg-primary bg-opacity-10">
<FontAwesomeIcon :icon="['fas', 'grip-lines']" class="px-2" />
</div>
<input type="text" :id="`category-name-${categoryIndex}`" v-model="category.name"
class="form-control rounded-0 h-100">
</div>
<div class="d-flex">
<button class="btn btn-primary rounded-0" @click="openCategory( categoryIndex )">
<FontAwesomeIcon :icon="['fas', 'edit']" size="sm" />
</button>
<div class="d-flex flex-column justify-content-center align-items-center h-100" role="group"
aria-label="Vertical button group">
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveCategoryUp( categoryIndex )"
:disabled="categoryIndex === 0">
<FontAwesomeIcon :icon="['fas', 'angle-up']" size="xs" />
</button>
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveCategoryDown( categoryIndex )"
:disabled="categoryIndex === board.categories.length - 1">
<FontAwesomeIcon :icon="['fas', 'angle-down']" size="xs" />
</button>
</div>
<button class="btn btn-danger rounded-start-0 rounded-0"
:class="[{ 'rounded-bottom-end': categoryIndex === board.categories.length - 1 }, { 'rounded-top-end': categoryIndex === 0 }]"
@click="deleteCategory( categoryIndex )">
<FontAwesomeIcon :icon="['fas', 'trash']" size="sm" />
</button>
</div>
</div>
</li>
</template>
</VueDraggable>
</template>
<label class="mt-2" for="new-category-name">{{ t( "board.category.add" ) }}</label>
<div class="input-group mb-3">
<input type="text" id="new-category-name" class="form-control" v-model="newCategoryName"
:placeholder="t( 'board.category.name' )" @keyup.enter="addCategory">
<button class="btn btn-primary" @click="addCategory">
<FontAwesomeIcon :icon="['fas', 'plus']" />
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>
@@ -0,0 +1,154 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { VueDraggable } from 'vue-draggable-plus';
import { BoardEntry } from '@/models/board/BoardEntry';
import { Answer } from '@/models/board/Answer';
import { AnswerType } from '@/models/board/AnswerType';
const { t } = useI18n();
const board = defineModel<Board>( { required: true } );
const props = defineProps<{
categoryIndex: number,
}>();
const emit = defineEmits<{
editBoardEntry: [categoryIndex: number, boardEntryIndex: number],
editBoard: [],
}>()
const newBoardEntryName = ref( '' );
function addBoardEntry() {
if( board.value.categories[props.categoryIndex].boardEntries.length >= 10 ) {
return;
}
const answer = new Answer('', AnswerType.TEXT);
const newBoardEntry = new BoardEntry( newBoardEntryName.value, answer, [] );
board.value.categories[props.categoryIndex].boardEntries.push( newBoardEntry );
}
function deleteBoardEntry( index: number ) {
board.value.categories[props.categoryIndex].boardEntries.splice( index, 1 );
}
function moveBoardEntryUp( index: number ) {
if( index === 0 || board.value.categories[props.categoryIndex].boardEntries.length <= 1 ) {
return;
}
const tmp = board.value.categories[props.categoryIndex].boardEntries[index];
board.value.categories[props.categoryIndex].boardEntries[index] = board.value.categories[props.categoryIndex].boardEntries[index - 1];
board.value.categories[props.categoryIndex].boardEntries[index - 1] = tmp;
}
function moveBoardEntryDown( index: number ) {
if( index === board.value.categories[props.categoryIndex].boardEntries.length - 1 || board.value.categories[props.categoryIndex].boardEntries.length <= 1 ) {
return;
}
const tmp = board.value.categories[props.categoryIndex].boardEntries[index];
board.value.categories[props.categoryIndex].boardEntries[index] = board.value.categories[props.categoryIndex].boardEntries[index + 1];
board.value.categories[props.categoryIndex].boardEntries[index + 1] = tmp;
}
function openBoardEntry( index: number ) {
emit("editBoardEntry", props.categoryIndex, index);
}
function openBoard() {
emit("editBoard");
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 p-2">
<div class="row">
<div class="col">
<div class="d-flex border-bottom border-3 border-primary align-items-center">
<button class="btn btn-sm btn-outline-primary mb-1" :title="t('board.category.back')" @click="openBoard">
<FontAwesomeIcon :icon="['fas', 'angle-left']"/>
</button>
<h2 class="flex-grow-1 ms-2">{{ t( "board.category.infos" ) }}</h2>
</div>
<h4 class="border-bottom border-2 border-primary">General Infos</h4>
<label for="category-name">{{ t( 'board.category.name' ) }}</label>
<input type="text" id="category-name" class="form-control mb-2" v-model="board.categories[props.categoryIndex].name" :placeholder="t( 'board.category.name' )">
<label for="category-description">{{ t( 'board.category.description' ) }}</label>
<textarea id="category-description" class="form-control" v-model="board.categories[props.categoryIndex].description" :placeholder="t( 'board.category.description' )">
</textarea>
<div class="form-check mt-2">
<input id="category-color-custom" type="checkbox" class="form-check-input" v-model="board.categories[props.categoryIndex].customColor">
<label for="category-color-custom">{{ t( 'board.category.custom-color' ) }}</label>
</div>
<input v-if="board.categories[props.categoryIndex].customColor" id="category-color" type="color" class="form-control" v-model="board.categories[props.categoryIndex].color"/>
</div>
</div>
<div class="row mt-3">
<div class="col">
<h4 class="border-bottom border-2 border-primary">{{ t( "board.boardentry.label", 2 ) }}</h4>
<template v-if=" board.categories[props.categoryIndex].boardEntries.length === 0 ">
<p>
{{ t( "board.boardentry.label", 0 ) }}
</p>
</template>
<template v-else>
<VueDraggable v-model="board.categories[props.categoryIndex].boardEntries" item-key="id" :animation="150" ghost-class="draggable-ghost"
tag="ul" class="list-group" handle=".drag-handle">
<template v-for="(boardEntry, boardEntryIndex) of board.categories[props.categoryIndex].boardEntries" :key="boardEntry.id">
<li class="list-group-item bg-body-secondary p-0">
<div class="d-flex justify-content-between w-100">
<div class="flex-grow-1 d-flex align-items-center g-3 justify-content-start">
<div
class="drag-handle h-100 d-flex justify-content-center align-items-center cursor-move border-end border-1 bg-primary bg-opacity-10">
<FontAwesomeIcon :icon="['fas', 'grip-lines']" class="px-2" />
</div>
<input type="text" :id="`category-name-${boardEntryIndex}`" v-model="boardEntry.name"
class="form-control rounded-0 h-100">
</div>
<div class="d-flex">
<button class="btn btn-primary rounded-0" @click="openBoardEntry( boardEntryIndex )">
<FontAwesomeIcon :icon="['fas', 'edit']" size="sm" />
</button>
<div class="d-flex flex-column justify-content-center align-items-center h-100" role="group"
aria-label="Vertical button group">
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveBoardEntryUp( boardEntryIndex )"
:disabled="boardEntryIndex === 0">
<FontAwesomeIcon :icon="['fas', 'angle-up']" size="xs" />
</button>
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveBoardEntryDown( boardEntryIndex )"
:disabled="boardEntryIndex === board.categories[props.categoryIndex].boardEntries.length - 1">
<FontAwesomeIcon :icon="['fas', 'angle-down']" size="xs" />
</button>
</div>
<button class="btn btn-danger rounded-start-0 rounded-0"
:class="[{ 'rounded-bottom-end': boardEntryIndex === board.categories[props.categoryIndex].boardEntries.length - 1 }, { 'rounded-top-end': boardEntryIndex === 0 }]"
@click="deleteBoardEntry( boardEntryIndex )">
<FontAwesomeIcon :icon="['fas', 'trash']" size="sm" />
</button>
</div>
</div>
</li>
</template>
</VueDraggable>
</template>
<label class="mt-2" for="new-category-name">{{ t( "board.boardentry.add" ) }}</label>
<div class="input-group mb-3">
<input type="text" id="new-category-name" class="form-control" v-model="newBoardEntryName"
:placeholder="t( 'board.boardentry.name' )" @keyup.enter="addBoardEntry">
<button class="btn btn-primary" @click="addBoardEntry">
<FontAwesomeIcon :icon="['fas', 'plus']" />
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>
@@ -0,0 +1,145 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { QuestionType } from '@/models/board/QuestionType';
import { useFileStore } from '@/stores/FileStore';
import { getFileKeyForQuestion } from '@/services/UtilService';
const { t } = useI18n();
const board = defineModel<Board>( { required: true } );
const props = defineProps<{
categoryIndex: number,
boardEntryIndex: number,
questionIndex: number;
}>();
const emit = defineEmits<{
editBoard: [],
editCategory: [categoryIndex: number],
editBoardEntry: [categoryIndex: number, boardEntryIndex: number],
}>();
const question = computed( () => {
return board.value.categories[props.categoryIndex].boardEntries[props.boardEntryIndex].questions[props.questionIndex];
} );
function openBoard() {
emit( "editBoard" );
}
function openCategory( categoryIndex: number ) {
emit( "editCategory", categoryIndex );
}
function openBoardEntry( categoryIndex: number, boardEntryIndex: number ) {
emit( "editBoardEntry", categoryIndex, boardEntryIndex );
}
const fileStore = useFileStore();
function newImageUploaded( event: Event ) {
const element = event.currentTarget as HTMLInputElement;
let files = element.files;
if( files === null || files.length === 0 ) {
return;
}
fileStore.addFile(files[0], getFileKeyForQuestion(props.categoryIndex, props.boardEntryIndex, props.questionIndex));
question.value.image = URL.createObjectURL(files[0]);
}
function newAudioUploaded( event: Event ) {
const element = event.currentTarget as HTMLInputElement;
let files = element.files;
if( files === null || files.length === 0 ) {
return;
}
fileStore.addFile(files[0], getFileKeyForQuestion(props.categoryIndex, props.boardEntryIndex, props.questionIndex));
question.value.audio = URL.createObjectURL(files[0]);
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 px-2">
<div class="row">
<div class="col">
<div class="d-flex align-items-center mb-2 overflow-x-auto pb-2">
<button class="btn btn-sm btn-outline-primary" :title="t( 'common.back' )"
@click="openBoardEntry( props.categoryIndex, props.boardEntryIndex )">
<FontAwesomeIcon :icon="['fas', 'angle-left']" />
</button>
<nav class="flex-grow-1 ms-2" aria-label="breadcrumb">
<ol class="breadcrumb mb-0 flex-nowrap">
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openBoard">
{{ board.boardName }}
</a>
</li>
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openCategory( props.categoryIndex )">
{{ board.categories[props.categoryIndex].name }}
</a>
</li>
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openBoardEntry( props.categoryIndex, props.boardEntryIndex )">
{{ board.categories[props.categoryIndex].boardEntries[props.boardEntryIndex].name }}
</a>
</li>
<li class="breadcrumb-item active text-truncate" style="max-width: 6em;" aria-current="page">
{{ question.text.length !== 0 ? question.text : t(`board.question.types.title.${question.questionType}`) }}
</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="d-flex border-bottom border-3 border-primary align-items-center mb-2">
<h2 class="flex-grow-1 ms-2">{{ t( "board.question.infos" ) }}</h2>
</div>
<label for="question-text">{{ t( 'board.question.text' ) }}</label>
<textarea id="question-text" v-model="question.text" class="form-control mb-2"
:placeholder="t( 'board.question.text' )"></textarea>
<label for="question-font-size-input">{{ t( 'board.question.fontsize' ) }}</label>
<input type="number" id="question-font-size-input" v-model="question.fontScaling" class="form-control mb-2">
<label for="board-entry-points">{{ t( 'board.question.type' ) }}</label>
<select id="question-type" v-model="question.questionType" class="form-select mb-2" aria-label="Question Type">
<template v-for=" questionType in QuestionType " :key="questionType">
<option :value="questionType" :title="t(`board.question.types.description.${questionType}`)">{{ t(`board.question.types.title.${questionType}`) }}</option>
</template>
</select>
<template v-if=" question.questionType === QuestionType.IMAGE ">
<label for="question-image-input">{{ t( 'board.question.upload.image' ) }}</label>
<input
id="question-image-input"
type="file"
class="form-control mb-2"
@change="newImageUploaded"
accept="image/png, image/jpeg"
>
</template>
<template v-if=" question.questionType === QuestionType.AUDIO ">
<label for="question-audio-input">{{ t( 'board.question.upload.audio' ) }}</label>
<input
id="question-audio-input"
type="file"
class="form-control mb-2"
@change="newAudioUploaded"
accept="audio/mpeg"
>
</template>
</div>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>
@@ -0,0 +1,16 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
</script>
<template>
<div class="row g-2 w-100">
<div class="col d-flex justify-content-around">
<button class="btn btn-primary">
{{ t('game.host.button.letNextChoose') }}
</button>
</div>
</div>
</template>
@@ -0,0 +1,47 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
const emit = defineEmits<{
lockQuestion: [delay: number],
}>()
const { t } = useI18n();
const delayBeforeLock = ref(0);
function lockQuestion(){
emit("lockQuestion", delayBeforeLock.value);
}
</script>
<template>
<div class="row g-2 w-100">
<div class="col-12">
<div class="row g-2">
<div class="col-5">
<button class="btn btn-primary w-100" @click="lockQuestion">
<FontAwesomeIcon :icon="['fas', 'lock']" />
{{ t('game.host.button.lockIn') }}
</button>
</div>
<div class="col-7 d-flex align-items-center">
<p class="mb-0 mx-1">
{{ t('game.host.text.in') }}
</p>
<input class="form-control" type="number" id="time-before-lock" v-model="delayBeforeLock">
<p class="mb-0 ms-1">
{{ t('game.host.text.seconds') }}
</p>
</div>
</div>
</div>
<div class="col-12">
<button class="btn btn-primary w-100">
<FontAwesomeIcon :icon="['fas', 'eye']" />
{{ t('game.host.button.revealAll') }}
</button>
</div>
</div>
</template>
@@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { onMounted, watch } from 'vue'; import { onMounted, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { onMounted, ref } from 'vue';
import { RouterLink, useRoute, useRouter } from 'vue-router'; import { RouterLink, useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@@ -21,6 +21,15 @@ const route = useRoute();
const userStore = useUserStore(); const userStore = useUserStore();
const navbar = ref<HTMLElement>();
defineExpose({
navElement: navbar
});
onMounted( () => {
console.log(typeof navbar.value);
})
const isActiveNav = ( navName: string ) => { const isActiveNav = ( navName: string ) => {
switch( navName ) { switch( navName ) {
case navNames.HOME: case navNames.HOME:
@@ -54,10 +63,10 @@ userStore.userCheckPromise
</script> </script>
<template> <template>
<nav id="navbar-main" class="navbar navbar-expand-lg bg-dark-accented"> <nav ref="navbar" id="navbar-main" class="navbar navbar-expand-lg bg-dark-accented">
<div class="container px-5"> <div class="container px-5">
<div class="position-absolute start-0 top-50 translate-middle-y d-flex ms-3 gap-3"> <div class="position-absolute start-0 top-50 translate-middle-y d-flex ms-3 gap-3 z-2">
<ThemeChanger /> <ThemeChanger />
<LocaleChanger /> <LocaleChanger />
</div> </div>
@@ -90,13 +99,13 @@ userStore.userCheckPromise
<div class="position-absolute end-0 top-50 translate-middle-y d-flex me-3 align-items-center"> <div class="position-absolute end-0 top-50 translate-middle-y d-flex me-3 align-items-center">
<template v-if=" userCheckLoading "> <template v-if=" userCheckLoading ">
<FontAwesomeIcon :icon="['fas', 'spinner']" spin />
</template> </template>
<template v-else-if=" userStore.loggedIn "> <template v-else-if=" userStore.loggedIn ">
<div class="dropdown-toggle pointer" data-bs-toggle="dropdown" aria-expanded="false"> <button class="dropdown-toggle pointer bg-dark py-1 px-2 btn" data-bs-toggle="dropdown" aria-expanded="false">
<img class="pfp-sizing rounded-circle border border-1 border-primary" :src="userStore.pfpSource" <img class="pfp-sizing rounded-circle border border-1 border-primary" :src="userStore.pfpSource"
alt="The Profile Pic of the user" /> alt="The Profile Pic of the user" />
</div> </button>
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end">
<li> <li>
<p class="dropdown-header fs-5 pt-0 text-primary fw-semibold">{{ userStore.getUserOutput }}</p> <p class="dropdown-header fs-5 pt-0 text-primary fw-semibold">{{ userStore.getUserOutput }}</p>
@@ -0,0 +1,121 @@
<script setup lang="ts">
import { useGameStore } from '@/stores/GameStore';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const gameStore = useGameStore();
function adjustPoints(){
}
</script>
<template>
<div class="row">
<div class="col">
<h3 class="border-bottom border-primary border-2">Players</h3>
</div>
</div>
<div class="row mb-3">
<div class="col">
<label for="points-manuel-adjustment-value">{{
t('game.pointsAdjustment')
}}</label>
<input
class="form-control form-control-sm"
type="number"
id="points-manuel-adjustment-value"
/>
</div>
</div>
<template v-for="player in gameStore.players" :key="player.uuid">
<div class="card bg-body-secondary mb-2">
<div class="card-header bg-primary p-2">
<div class="row">
<div class="col d-flex justify-content-between">
<span class="text-break me-3">
<FontAwesomeIcon
v-if="player.isAnswering"
:icon="['fas', 'angles-right']"
class="text-dark"
beat-fade
/>
<FontAwesomeIcon
v-if="player.isChoosing"
:icon="['fas', 'hand-pointer']"
class="text-dark"
/>
{{ player.name }}
</span>
<span>
{{ player.points }}
</span>
</div>
</div>
</div>
<div class="card-body p-2">
<div class="row">
<div class="col-3">Answer</div>
<div class="col-9">
<input
class="form-control form-control-sm"
type="text"
id="points-player-nr"
value=""
readonly
/>
</div>
</div>
<div v-if="gameStore.isHost" class="row mt-2">
<div class="col">
<div class="row g-2">
<div class="col-6">
<button class="btn btn-sm btn-outline-primary w-100" @click="adjustPoints()">
<FontAwesomeIcon :icon="['fas', 'plus']" />
{{ t('game.host.button.pointsAdd') }}
</button>
</div>
<div class="col-6">
<button class="btn btn-sm btn-outline-primary w-100" @click="adjustPoints()">
<FontAwesomeIcon :icon="['fas', 'minus']" />
{{ t('game.host.button.pointsSubtract') }}
</button>
</div>
<div class="col-6">
<button class="btn btn-sm btn-outline-primary w-100 me-2">
<FontAwesomeIcon :icon="['fas', 'eye']" />
{{ t('game.host.button.reveal') }}
</button>
</div>
<div class="col-6">
<button class="btn btn-sm btn-outline-primary w-100">
<FontAwesomeIcon :icon="['fas', 'hand-pointer']" />
{{ t('game.host.button.letChoose') }}
</button>
</div>
<div class="col-12">
<button class="btn btn-sm btn-outline-primary w-100">
<FontAwesomeIcon :icon="['fas', 'lock-open']" />
{{ t('game.host.button.unlock') }}
</button>
</div>
<template v-if="false /* isQuestion Locked */">
<div class="col-6">
<button class="btn btn-sm btn-success w-100">
{{ t('game.host.button.correct') }}
</button>
</div>
<div class="col-6">
<button class="btn btn-sm btn-danger w-100">
{{ t('game.host.button.wrong') }}
</button>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</template>
</template>
@@ -0,0 +1,195 @@
<script setup lang="ts">
import { computed, inject, ref, type Ref } from 'vue';
import { navbarKey } from '@/services/UtilService';
import { Board } from '@/models/board/Board';
import { BoardEntry } from '@/models/board/BoardEntry';
import type NavBar from '@/components/blocks/NavBar.vue';
import BoardView from '@/components/blocks/BoardView.vue';
import CreatePanel from '@/components/blocks/CreatePanel.vue';
import BoardEntryView from '@/components/blocks/BoardEntryView.vue';
import { userService } from '@/services/UserService';
import { useRoute, useRouter } from 'vue-router';
import { useFileStore } from '@/stores/FileStore';
const navbar = inject<Ref<InstanceType<typeof NavBar> | null>>(navbarKey);
const navbarHeight = computed(() => {
return navbar?.value?.navElement?.clientHeight;
});
const restHeight = computed(() => {
return { height: `calc(100vh - ${navbarHeight.value}px)` };
});
const board = ref<Board>(new Board('New Board'));
const categoryIndex = ref<number | null>(null);
const boardEntryIndex = ref<number | null>(null);
const questionIndex = ref<number | null>(null);
function showQuestionLayer(cIndex: number, bEIndex: number, qIndex: number) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = qIndex;
}
function showBoardEntry(cIndex: number, bEIndex: number) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = null;
}
function showCategory(cIndex: number) {
categoryIndex.value = cIndex;
boardEntryIndex.value = null;
questionIndex.value = null;
}
function showBoard() {
categoryIndex.value = null;
boardEntryIndex.value = null;
questionIndex.value = null;
}
const isQuestionShown = ref(true);
const isAnswerShown = ref(true);
function showQuestion() {
isQuestionShown.value = true;
}
function hideQuestion() {
isQuestionShown.value = false;
}
function showAnswer() {
isAnswerShown.value = true;
}
function hideAnswer() {
isAnswerShown.value = false;
}
const fileStore = useFileStore();
const savingBoardInProgress = ref(false);
function saveBoard() {
savingBoardInProgress.value = true;
const formData: FormData = new FormData();
formData.set('board', new Blob([JSON.stringify(board.value)], { 'type': 'application/json' } ));
for( const file of fileStore.files ){
formData.append('files', file.data, `${file.category}-${file.boardEntry}-${file.answer ? 'answer' : file.question!}`);
}
let savePromise;
if( board.value.id ){
savePromise = userService.updateBoard(board.value, formData);
} else {
savePromise = userService.saveNewBoard(formData);
}
savePromise
.then((savedBoard) => {
board.value = savedBoard;
if( !route.params.boardId ){
router.replace({
name: 'create',
params: {
boardId: savedBoard.id
}
});
}
})
.catch( (error) => {
console.error(error);
})
.finally( () => {
savingBoardInProgress.value = false;
});
}
function exit() {
//TODO
}
const boardLoading = ref(true);
const route = useRoute();
const router = useRouter();
if (route.params.boardId) {
userService
.getBoard(route.params.boardId as string)
.then((boardResponse) => {
board.value = boardResponse;
})
.catch((error) => {
console.error(error);
})
.finally(() => {
boardLoading.value = false;
});
} else {
boardLoading.value = false;
}
</script>
<template>
<div :style="restHeight">
<div class="row h-100">
<div class="col-9 h-100 pe-0">
<template v-if="boardLoading">
<FontAwesomeIcon :icon="['fas', 'spinner']" size="xl" spin />
</template>
<template v-else>
<BoardEntryView
v-if="categoryIndex !== null && boardEntryIndex !== null"
:boardEntry="( board.categories[categoryIndex].boardEntries[boardEntryIndex] as BoardEntry )"
:categoryName="board.categories[categoryIndex].name"
:selectedQuestionIndex="questionIndex ?? 0"
@questionSelected="( qIndex ) => showQuestionLayer( categoryIndex!, boardEntryIndex!, qIndex )"
:isQuestionShown="isQuestionShown"
:isAnswerShown="isAnswerShown"
@showQuestion="showQuestion"
@hideQuestion="hideQuestion"
@showAnswer="showAnswer"
@hideAnswer="hideAnswer"
@showBoard="showBoard"
/>
<BoardView
v-else
:board="( board as Board )"
@categorySelected="showCategory"
@boardEntrySelected="showBoardEntry"
/>
</template>
</div>
<div
class="col-3 ps-0 h-100 overflow-auto border-start border-2 border-primary"
>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 overflow-y-auto p-2">
<CreatePanel
v-model="( board as Board )"
:categoryIndex="categoryIndex"
:boardEntryIndex="boardEntryIndex"
:questionIndex="questionIndex"
@editBoard="showBoard"
@editCategory="showCategory"
@editBoardEntry="showBoardEntry"
@editQuestion="showQuestionLayer"
/>
</div>
<div class="border-top border-2 border-primary p-2">
<div class="d-flex align-items-center">
<div class="flex-grow-1 me-1">
<button class="btn btn-primary w-100" @click="saveBoard">
<FontAwesomeIcon v-if="savingBoardInProgress" :icon="['fas', 'spinner']" spin />
<FontAwesomeIcon v-else :icon="['fas', 'save']" />
Save
</button>
</div>
<div class="flex-grow-1 ms-1">
<button class="btn btn-danger w-100" @click="exit">
<FontAwesomeIcon :icon="['fas', 'xmark']" />
Exit
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -1,12 +1,140 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n'; import { computed, inject, ref, type Ref } from 'vue';
const { t } = useI18n(); import { navbarKey } from '@/services/UtilService';
import { Board } from '@/models/board/Board';
import { Category } from '@/models/board/Category';
import { BoardEntry } from '@/models/board/BoardEntry';
import { Answer } from '@/models/board/Answer';
import { AnswerType } from '@/models/board/AnswerType';
import type NavBar from '@/components/blocks/NavBar.vue';
import BoardView from '@/components/blocks/BoardView.vue';
import BoardEntryView from '@/components/blocks/BoardEntryView.vue';
import PlayersPanel from '@/components/blocks/PlayersPanel.vue';
import { useGameStore } from '@/stores/GameStore';
import HostInteractionsBoard from '../blocks/HostInteractionsBoard.vue';
import HostInteractionsEntry from '../blocks/HostInteractionsEntry.vue';
const gameStore = useGameStore();
const navbar = inject<Ref<InstanceType<typeof NavBar> | null>>(navbarKey);
const navbarHeight = computed(() => {
return navbar?.value?.navElement?.clientHeight;
});
const restHeight = computed(() => {
return { height: `calc(100vh - ${navbarHeight.value}px)` };
});
const board = ref<Board>(new Board('New Board'));
const board1 = ref<Board>(
new Board('New Board', [
new Category('Test1', ''),
new Category('Test2', ''),
])
);
const answer = new Answer(
'',
AnswerType.TEXT
);
const newBoardEntry = new BoardEntry(
'Test Entry 1',
answer,
[]
);
board1.value.categories[0].boardEntries.push(newBoardEntry);
const categoryIndex = ref<number | null>(null);
const boardEntryIndex = ref<number | null>(null);
const questionIndex = ref<number | null>(null);
function showQuestionLayer(cIndex: number, bEIndex: number, qIndex: number) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = qIndex;
}
function showBoardEntry(cIndex: number, bEIndex: number) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = null;
}
function showBoard() {
categoryIndex.value = null;
boardEntryIndex.value = null;
questionIndex.value = null;
}
const isBoardShown = computed( () => {
return categoryIndex.value === null && boardEntryIndex.value === null && questionIndex.value === null;
});
const isQuestionShown = ref(true);
const isAnswerShown = ref(true);
function showQuestion() {
isQuestionShown.value = true;
}
function hideQuestion() {
isQuestionShown.value = false;
}
function showAnswer() {
isAnswerShown.value = true;
}
function hideAnswer() {
isAnswerShown.value = false;
}
</script> </script>
<template> <template>
<div> <div :style="restHeight">
{{ t( 'about.whatis' ) }} <div class="row h-100">
<div class="col-9 h-100 pe-0">
<BoardEntryView
v-if="categoryIndex !== null && boardEntryIndex !== null"
:boardEntry="( board1.categories[categoryIndex].boardEntries[boardEntryIndex] as BoardEntry )"
:categoryName="board1.categories[categoryIndex].name"
:selectedQuestionIndex="questionIndex ?? 0"
@questionSelected="( qIndex ) => showQuestionLayer( categoryIndex!, boardEntryIndex!, qIndex )"
:isQuestionShown="isQuestionShown"
:isAnswerShown="isAnswerShown"
@showQuestion="showQuestion"
@hideQuestion="hideQuestion"
@showAnswer="showAnswer"
@hideAnswer="hideAnswer"
@showBoard="showBoard"
/>
<BoardView
v-else
:board="( board1 as Board )"
@boardEntrySelected="showBoardEntry"
/>
</div>
<div
class="col-3 ps-0 h-100 overflow-auto border-start border-2 border-primary"
>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 overflow-y-auto p-2 overflow-x-hidden">
<PlayersPanel />
</div>
<div class="border-top border-2 border-primary p-2">
<template v-if="gameStore.isHost">
<div class="d-flex align-items-center">
<template v-if="isBoardShown">
<HostInteractionsBoard />
</template>
<template v-else>
<HostInteractionsEntry />
</template>
</div>
</template>
<template v-else>
<div class="d-flex align-items-center">
<PlayerActionPanel />
</div>
</template>
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>
@@ -3,8 +3,11 @@ import { ref, onMounted } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userService } from '@/services/UserService'; import { userService } from '@/services/UserService';
import { useGameStore } from '@/stores/GameStore';
import IconJeobeardy from '@/components/icons/IconJeobeardy.vue'; import IconJeobeardy from '@/components/icons/IconJeobeardy.vue';
import { useRouter } from 'vue-router';
import type { AxiosError } from 'axios';
const { t } = useI18n(); const { t } = useI18n();
@@ -17,6 +20,48 @@ onMounted( () => {
} ); } );
} ); } );
const gameStore = useGameStore()
const router = useRouter();
const inviteCode = ref('');
const joinLoading = ref(false);
const joinError = ref<null | string>(null);
function joinGame(){
joinLoading.value = true;
gameStore.initGame(inviteCode.value)
.then( (game) => {
router.push({name: 'join', params: { gameUuid: game.uuid } } )
})
.catch( (error: AxiosError) => {
joinError.value = error.message;
})
.finally(() => {
joinLoading.value = false;
})
}
const hostLoading = ref(false);
const hostError = ref<null | string>(null);
const errorTimeout = ref<number | null>(null)
function startHost(){
hostLoading.value = true;
gameStore.startHost()
.then( (game) => {
router.push({name: 'lobby', params: { gameUuid: game.uuid } } )
})
.catch( (error: AxiosError) => {
hostError.value = error.message ?? null;
if( errorTimeout.value ){
clearTimeout(errorTimeout.value);
}
errorTimeout.value = setTimeout(() => {
hostError.value = null;
}, 5000);
})
.finally(() => {
hostLoading.value = false;
})
}
</script> </script>
<template> <template>
@@ -46,10 +91,14 @@ onMounted( () => {
</p> </p>
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
<input type="text" class="form-control" placeholder="Code"> <input type="text" class="form-control" placeholder="Code" v-model="inviteCode">
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button class="btn btn-primary">{{ t("join.button") }}</button> <button class="btn btn-primary" @click="joinGame">
<FontAwesomeIcon v-if="joinLoading" :icon="['fas', 'spinner']" spin/>
<FontAwesomeIcon v-else :icon="['fas', 'arrow-right-to-bracket']" />
{{ t("join.button") }}
</button>
</div> </div>
</div> </div>
</div> </div>
@@ -70,19 +119,21 @@ onMounted( () => {
{{ t("host.text") }} {{ t("host.text") }}
</h3> </h3>
<p> <p>
{{ t("host.alreadyHostedGome") }} {{ t("host.alreadyCreatedBoard") }}
</p> </p>
<p> <p>
{{ t("host.textCode") }} {{ t("host.startHost") }}
</p> </p>
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
<input type="text" class="form-control" placeholder="Code"> <button class="btn btn-primary" @click="startHost">
</div> <FontAwesomeIcon v-if="hostLoading" :icon="['fas', 'spinner']" spin/>
<div class="col-auto"> <FontAwesomeIcon v-else :icon="['fas', 'users']"/>
<button class="btn btn-primary">{{ t("host.button") }}</button> {{ t("host.button") }}
</button>
</div> </div>
</div> </div>
<p v-show="hostError !== null">{{ hostError }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -0,0 +1,175 @@
<script setup lang="ts">
import { GAME_STATUS_CONST } from '@/services/GameService';
import { useGameStore } from '@/stores/GameStore';
import { useUserStore } from '@/stores/UserStore';
import type { AxiosError } from 'axios';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const gameStore = useGameStore();
const userStore = useUserStore();
const playerName = ref('');
const inviteCode = ref('');
function backOrHome(){
if( window.history.length - userStore.initialHistoryLen > 0 ){
router.back();
} else {
router.push({name: 'home'});
}
}
function loadGame(){
gameStore
.initGame(inviteCode.value)
.catch((error: AxiosError) => {
joinError.value = error.message;
console.error(error);
})
.finally(() => {
joinLoading.value = false;
});
}
function joinGame(){
joinLoading.value = true;
gameStore.joinGame(playerName.value)
.then( () => {
if( gameStore.gameStatus === GAME_STATUS_CONST.lobby ) {
router.push({name: 'lobby', params: { gameUuid: gameId}})
}
if( gameStore.gameStatus === GAME_STATUS_CONST.inProgress ) {
router.push({name: 'game', params: { gameUuid: gameId}})
}
})
.catch( (error) => {
console.error(error);
})
.finally( () => {
joinLoading.value = false;
})
}
const joinError = ref<string | null>(null);
const joinLoading = ref(false);
const showingInviteCodeInput = ref(false);
const gameId = route.params.gameUuid as string | undefined;
const siteLoading = ref(true);
function initGame(gameId: string){
gameStore
.initGame(gameId)
.catch((error: AxiosError) => {
joinError.value = error.message;
showingInviteCodeInput.value = true;
})
.finally( () => {
siteLoading.value = false;
})
}
function checkIfGameSavedInSessionAndIsSameAsRoute(){
const sessionGame = gameStore.checkForGame();
if( sessionGame === null ){
if( gameId === undefined ){
showingInviteCodeInput.value = true;
siteLoading.value = false;
} else {
initGame(gameId);
}
} else {
if( gameId === undefined ){
showingInviteCodeInput.value = true;
inviteCode.value = sessionGame.inviteCode;
siteLoading.value = false;
} else {
if( gameId === sessionGame.uuid && !gameStore.isConnected ){
initGame(gameId);
return;
}
if( gameId === sessionGame.inviteCode && !gameStore.isConnected ){
initGame(gameId);
return;
}
siteLoading.value = false;
}
}
}
checkIfGameSavedInSessionAndIsSameAsRoute();
</script>
<template>
<div
class="d-flex flex-column w-100 justify-content-start align-items-center"
>
<div class="row mt-5">
<div class="col">
<template v-if="showingInviteCodeInput">
<div class="card">
<div class="card-header">
<h4>Join Game</h4>
</div>
<div class="card-body">
<label for="invite-code-input">{{ t("join.textCode") }}</label>
<input
class="form-control"
type="text"
id="invite-code-input"
v-model="inviteCode"
/>
<div class="d-flex justify-content-between align-items-center mt-3">
<button class="btn btn-outline-danger" @click="backOrHome">
<FontAwesomeIcon :icon="['fas', 'xmark']" />
Cancel
</button>
<button class="btn btn-primary" @click="loadGame">
Join
<FontAwesomeIcon :icon="['fas', 'arrow-right-to-bracket']" />
</button>
</div>
<p class="text-danger">{{ joinError }}</p>
</div>
</div>
</template>
<template v-else>
<div class="card">
<div class="card-header">
<h4>Join Game</h4>
</div>
<div class="card-body">
<ul>
<li>Host: {{ gameStore.hostUsername }}</li>
<li>Players: {{ gameStore.playerCount }}</li>
<li>Status: {{ t(gameStore.gameStatus) }}</li>
</ul>
<label for="player-name-input">{{ t('game.player.name') }}</label>
<input
class="form-control"
type="text"
id="player-name-input"
v-model="playerName"
/>
<div class="d-flex justify-content-between align-items-center mt-3">
<button class="btn btn-outline-danger" @click="backOrHome">
<FontAwesomeIcon :icon="['fas', 'xmark']" />
Cancel
</button>
<button class="btn btn-primary" @click="joinGame">
Join
<FontAwesomeIcon :icon="['fas', 'arrow-right-to-bracket']" />
</button>
</div>
<p class="text-danger">{{ joinError }}</p>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
@@ -0,0 +1,130 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useClipboard } from '@vueuse/core';
import { userService } from '@/services/UserService';
import { useGameStore } from '@/stores/GameStore';
import { Board } from '@/models/board/Board';
import IconJeobeardy from '@/components/icons/IconJeobeardy.vue';
const { t } = useI18n();
const gameStore = useGameStore();
const boardSearchText = ref('');
const boardsLoading = ref(true);
const hostBoards = ref<Array<Board>>([])
if( gameStore.isHost ){
userService.getBoardsForUser()
.then( (boards) => {
hostBoards.value = boards;
} )
.catch( (error) => {
})
.finally( () => {
boardsLoading.value = false;
})
}
function startGame(){
gameStore.startGame();
}
const { copy, copied } = useClipboard();
</script>
<template>
<div
class="d-flex flex-column w-100 justify-content-start align-items-center"
>
<div class="row w-100 mt-4 mb-3">
<div :class="[{'col-6': gameStore.isHost},{'col-12': !gameStore.isHost}]" class="d-flex justify-content-center align-items-center gap-3">
<h4>Invite Code:</h4>
<div class="input-group w-invite-code">
<input
type="text"
class="form-control"
aria-label="Invite code"
readonly
:value="gameStore.gameInviteCode"
/>
<button
class="btn btn-outline-primary"
type="button"
id="copy-invite-code-to-clipboard"
@click="copy(gameStore.gameInviteCode ?? '')"
>
<FontAwesomeIcon :icon="['fas', 'copy']" />
<span v-if="copied" class="badge pe-0">
<FontAwesomeIcon :icon="['fas', 'check']" />
</span>
</button>
</div>
</div>
<div v-if="gameStore.isHost" class="col-6 d-flex justify-content-center align-items-center">
<button class="btn btn-primary" @click="startGame">
Start Game
<FontAwesomeIcon :icon="['fas', 'arrow-right']" />
</button>
</div>
</div>
<template v-if="gameStore.isHost">
<div class="row w-100 my-2 p-2 bg-body-secondary">
<div class="col-12 col-lg-9 text-start">
<h4>Boards</h4>
</div>
<div class="col-12 col-lg-3">
<input
class="form-control"
type="search"
id="search-for-board"
v-model="boardSearchText"
placeholder="Search for a board"
/>
</div>
</div>
<div class="row w-100 mb-3 pb-3 bg-body-secondary g-3 text-center">
<template v-if="boardsLoading">
<IconJeobeardy class="spinny-spin spinny-size" />
</template>
<template v-else>
<template v-for="board in hostBoards" :key="board.uuid">
<div class="col-12 col-lg-4">
<div class="card p-2">
{{ board.boardName }}
</div>
</div>
</template>
</template>
</div>
</template>
<div class="row">
<div class="col">
<h3>Players</h3>
</div>
</div>
<div class="row w-100 px-3">
<div class="col-12 col-lg-3">
<template v-for="player in gameStore.players" :key="player.uuid">
<div class="card bg-body-secondary p-2">
{{ player.name }}
</div>
</template>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.w-invite-code {
width: 12em;
}
.spinny-size{
max-width: 6.66em;
max-height: 6.66em;
}
</style>
Loaded 100 of 127 files, more files were not shown because too many files have changed in this diff. Show more