Modificação na area do motorista
This commit is contained in:
@@ -1,27 +1,30 @@
|
|||||||
// app/javascript/controllers/carrossel_controller.js
|
// app/javascript/controllers/carrossel_controller.js
|
||||||
// Stimulus — paginação em "carrossel" para listas longas: mostra N itens por vez
|
// Stimulus — paginação em "carrossel" para listas longas: mostra uma página de
|
||||||
// com setas grandes e o indicador "1–10 de 12".
|
// itens por vez, com setas grandes e o indicador "1–5 de 12".
|
||||||
//
|
//
|
||||||
// PADRÃO EM TELA PEQUENA, LISTA INTEIRA EM TELA GRANDE. Em celular e monitor
|
// TAMANHO DE PÁGINA POR TELA (é o ponto do controller):
|
||||||
// pequeno, uma lista de 30 cards vira rolagem infinita e o rodapé/ações da tela
|
// • celular (até 640px) → 5 itens — cada card ocupa muita altura;
|
||||||
// somem de vista; num monitor grande a mesma lista cabe e paginar só atrapalha
|
// 10 já viravam rolagem infinita;
|
||||||
// (Ctrl+F do navegador não acha o que está escondido). O corte é por largura de
|
// • até 1366px → 10 itens — tablet e notebook pequeno;
|
||||||
// janela — `maxLargura` — e é reavaliado no resize/rotação da tela.
|
// • acima disso → lista INTEIRA, sem setas. Em monitor grande a
|
||||||
|
// lista cabe e esconder item só atrapalha (o
|
||||||
|
// Ctrl+F do navegador não acha o que está oculto).
|
||||||
|
//
|
||||||
|
// O corte é reavaliado no resize/rotação: girar o celular ou encostar a janela
|
||||||
|
// na lateral já muda o comportamento, e o item que estava no topo continua na
|
||||||
|
// tela (a posição é guardada pelo ÍNDICE do item, não pelo número da página).
|
||||||
//
|
//
|
||||||
// Os itens já vêm todos no HTML; aqui só escondemos os de fora da página. Por
|
// Os itens já vêm todos no HTML; aqui só escondemos os de fora da página. Por
|
||||||
// isso não serve para listas de centenas de itens (aí é paginação no servidor).
|
// isso não serve para listas de centenas de itens (aí é paginação no servidor).
|
||||||
//
|
//
|
||||||
// Uso:
|
// Uso:
|
||||||
// <div data-controller="carrossel"
|
// <div data-controller="carrossel"
|
||||||
// data-carrossel-tamanho-value="10" <- itens por página
|
// data-carrossel-tamanho-value="10" <- itens por página
|
||||||
// data-carrossel-max-largura-value="1366"> <- acima disso, mostra tudo
|
// data-carrossel-tamanho-compacto-value="5" <- itens no celular
|
||||||
// <div data-carrossel-target="item">…</div> <- cada item
|
// data-carrossel-largura-compacta-value="640" <- até aqui é "celular"
|
||||||
// …
|
// data-carrossel-max-largura-value="1366"> <- acima disso, mostra tudo
|
||||||
// <div data-carrossel-target="controles" class="hidden">
|
// <div data-carrossel-target="item">…</div>
|
||||||
// <button data-action="carrossel#anterior" data-carrossel-target="anterior">
|
// <%= render 'shared/carrossel_controles' %>
|
||||||
// <span data-carrossel-target="indicador"></span>
|
|
||||||
// <button data-action="carrossel#proxima" data-carrossel-target="proximo">
|
|
||||||
// </div>
|
|
||||||
// </div>
|
// </div>
|
||||||
//
|
//
|
||||||
// Um item com data-carrossel-inicial="true" (ex.: o motorista com a composição
|
// Um item com data-carrossel-inicial="true" (ex.: o motorista com a composição
|
||||||
@@ -32,12 +35,17 @@ import { Controller } from "@hotwired/stimulus"
|
|||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["item", "controles", "indicador", "anterior", "proximo"]
|
static targets = ["item", "controles", "indicador", "anterior", "proximo"]
|
||||||
static values = {
|
static values = {
|
||||||
tamanho: { type: Number, default: 10 },
|
tamanho: { type: Number, default: 10 },
|
||||||
maxLargura: { type: Number, default: 1366 }
|
tamanhoCompacto: { type: Number, default: 5 },
|
||||||
|
larguraCompacta: { type: Number, default: 640 },
|
||||||
|
maxLargura: { type: Number, default: 1366 }
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
this.pagina = this.paginaInicial()
|
// Âncora = índice do primeiro item da página atual. Guardar o ÍNDICE (e não
|
||||||
|
// o número da página) é o que mantém o mesmo item na tela quando o tamanho
|
||||||
|
// da página muda junto com a largura.
|
||||||
|
this.ancora = this.indiceInicial()
|
||||||
this._aoRedimensionar = () => this.render()
|
this._aoRedimensionar = () => this.render()
|
||||||
window.addEventListener("resize", this._aoRedimensionar)
|
window.addEventListener("resize", this._aoRedimensionar)
|
||||||
this.render()
|
this.render()
|
||||||
@@ -51,26 +59,37 @@ export default class extends Controller {
|
|||||||
anterior() { this.ir(this.pagina - 1) }
|
anterior() { this.ir(this.pagina - 1) }
|
||||||
|
|
||||||
ir(destino) {
|
ir(destino) {
|
||||||
this.pagina = Math.min(Math.max(destino, 0), this.totalPaginas - 1)
|
const pagina = Math.min(Math.max(destino, 0), this.totalPaginas - 1)
|
||||||
|
this.ancora = pagina * this.tamanho
|
||||||
this.render()
|
this.render()
|
||||||
// Volta ao topo da lista: sem isso, na 2ª página o leitor continua vendo o
|
// Volta ao topo da lista: sem isso, na página seguinte o leitor continua
|
||||||
// fim da anterior e parece que nada mudou.
|
// vendo o fim da anterior e parece que nada mudou.
|
||||||
this.element.scrollIntoView({ behavior: "smooth", block: "start" })
|
this.element.scrollIntoView({ behavior: "smooth", block: "start" })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get tamanho() {
|
||||||
|
return window.innerWidth <= this.larguraCompactaValue
|
||||||
|
? this.tamanhoCompactoValue
|
||||||
|
: this.tamanhoValue
|
||||||
|
}
|
||||||
|
|
||||||
// Tela grande: sem paginação (a lista inteira aparece).
|
// Tela grande: sem paginação (a lista inteira aparece).
|
||||||
get paginando() {
|
get paginando() {
|
||||||
return window.innerWidth <= this.maxLarguraValue &&
|
return window.innerWidth <= this.maxLarguraValue &&
|
||||||
this.itemTargets.length > this.tamanhoValue
|
this.itemTargets.length > this.tamanho
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalPaginas() {
|
get totalPaginas() {
|
||||||
return Math.max(Math.ceil(this.itemTargets.length / this.tamanhoValue), 1)
|
return Math.max(Math.ceil(this.itemTargets.length / this.tamanho), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
paginaInicial() {
|
get pagina() {
|
||||||
|
return Math.min(Math.floor(this.ancora / this.tamanho), this.totalPaginas - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
indiceInicial() {
|
||||||
const i = this.itemTargets.findIndex((el) => el.dataset.carrosselInicial === "true")
|
const i = this.itemTargets.findIndex((el) => el.dataset.carrosselInicial === "true")
|
||||||
return i < 0 ? 0 : Math.floor(i / this.tamanhoValue)
|
return i < 0 ? 0 : i
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -82,11 +101,8 @@ export default class extends Controller {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uma tela menor pode ter reduzido o total de páginas desde a última vez.
|
const inicio = this.pagina * this.tamanho
|
||||||
this.pagina = Math.min(this.pagina, this.totalPaginas - 1)
|
const fim = inicio + this.tamanho
|
||||||
|
|
||||||
const inicio = this.pagina * this.tamanhoValue
|
|
||||||
const fim = inicio + this.tamanhoValue
|
|
||||||
|
|
||||||
this.itemTargets.forEach((item, i) => {
|
this.itemTargets.forEach((item, i) => {
|
||||||
item.classList.toggle("hidden", i < inicio || i >= fim)
|
item.classList.toggle("hidden", i < inicio || i >= fim)
|
||||||
@@ -96,7 +112,7 @@ export default class extends Controller {
|
|||||||
this.controlesTarget.classList.remove("hidden")
|
this.controlesTarget.classList.remove("hidden")
|
||||||
|
|
||||||
if (this.hasIndicadorTarget) {
|
if (this.hasIndicadorTarget) {
|
||||||
// "1–10 de 12" e não "página 1 de 2": quem lê quer saber quantos itens
|
// "1–5 de 12" e não "página 1 de 3": quem lê quer saber quantos itens
|
||||||
// existem, não quantas páginas a tela tem.
|
// existem, não quantas páginas a tela tem.
|
||||||
this.indicadorTarget.textContent = `${inicio + 1}–${Math.min(fim, total)} de ${total}`
|
this.indicadorTarget.textContent = `${inicio + 1}–${Math.min(fim, total)} de ${total}`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user