224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/docs/relatorio/relatorioTecnico.md:
--------------------------------------------------------------------------------
1 | # Informações do Projeto:
2 |
3 | ### `TÍTULO:` **Event Manager**
4 |
5 | ### `CURSO:` **Engenharia de Software**
6 |
7 | ## Participantes:
8 |
9 | * Luís Felipe Teixeira Dias Brescia
10 | * Bernardo Carvalho Denucci Mercado
11 | * Thiago Cury Freire
12 | * Vitor Rebula Nogueira
13 |
14 | # Estrutura do Documento
15 |
16 | - [Informações do Projeto](#informações-do-projeto)
17 | - [Participantes](#participantes)
18 | - [Estrutura do Documento](#estrutura-do-documento)
19 | - [Introdução](#introdução)
20 | - [Problema](#problema)
21 | - [Objetivos](#objetivos)
22 | - [Justificativa](#justificativa)
23 | - [Público-Alvo](#público-alvo)
24 | - [Especificações do Projeto](#especificações-do-projeto)
25 | - [Personas e Mapas de Empatia](#personas-e-mapas-de-empatia)
26 | - [Histórias de Usuários](#histórias-de-usuários)
27 | - [Requisitos](#requisitos)
28 | - [Requisitos Funcionais](#requisitos-funcionais)
29 | - [Requisitos não Funcionais](#requisitos-não-funcionais)
30 | - [Restrições](#restrições)
31 | - [Userflow](#projeto-de-interface)
32 | - [Metodologia](#metodologia)
33 | - [Ferramentas](#ferramentas)
34 | - [Controle de Versão](#controle-de-versão)
35 | - [Projeto da Solução](#projeto-da-solução)
36 | - [Tecnologias Utilizadas](#tecnologias-utilizadas)
37 | - [Arquitetura da solução](#arquitetura-da-solução)
38 | - [Avaliação da Aplicação](#avaliação-da-aplicação)
39 | - [Plano de Testes](#plano-de-testes)
40 | - [Registros de Testes](#registros-de-testes)
41 | - [Referências](#referências)
42 |
43 |
44 | # Introdução
45 |
46 | Neste contexto a palavra "evento" pode significar qualquer tipo de atividade onde tenha múltiplas pessoas envolvidas, como um jogo de futebol, ida a um show, campanha beneficente de moletom, churrasco, festa de formatura, casamento, uma saida com os amigos, desenvolvimento de um jogo, criação de uma música, acampamento, viagem em grupo, entre outros.
47 |
48 | Dito isso, durante o planejmanto de um evento devemos levar em consideração diversos fatores, dentre eles, número de convidados, local, comida, bebida, fotógrafo, motorista, ingresso.
49 |
50 | ## Problema
51 |
52 | A dificuldade não está apenas em avaliar quais serão os gastos necessários e estimar o valor de cada um deles, mas também em encontrar alguém para suprir aquela demanda, o que atualemente costuma ser feito por pesquisas na internet, indicação de amigos, redes sociais... O que pode ser um processo demorado e cansativo, além de dificultar a comparação de preços e não garantir a qualidade do serviço.
53 |
54 | ## Objetivos
55 |
56 | Juntar de uma forma concisa ferramentes necessárias para o planejamento de um evento, desenvolvendo uma forma mais eficiente, fácil, e rápida de planeja-lo.
57 |
58 | Como objetivos específicos, podemos ressaltar:
59 | * Estimar valor de um evento.
60 | * Estimar a quantidade de cada insumo em um evento.
61 | * Organizar e armazenar dados sobre o evento.
62 | * Facilitar a conexão entre o organizador e os fornecedores.
63 |
64 | ## Justificativa
65 |
66 | Diversas pessoas utilizam ferramentas como excel, whatsapp, e até mesmo papel e caneta para organizar seus eventos, acreditamos que uma ferramenta que junte todas essas funcionalidades em um só lugar, de forma simples e intuitiva, pode ser muito útil para o público alvo, já que atualmente nenhuma ferramenta acessível é capaz de fazer isso de forma dinâmica, permitindo alterações tanto do organizador quanto do fornecedor.
67 |
68 | ## Público-Alvo
69 |
70 | Tanto organizadores de eventos quanto fornecedores podem se beneficiar do site, porém, o foco no momento é direcionado aos organizadores, visto que o site sem eles não funcionaria.
71 |
72 | # Especificações do Projeto
73 |
74 | Nesta parte do documento será abordado de forma objetiva os problemas que a aplicação busca resolver, bem como as funcionalidades que ela deve apresentar. Para tanto, iremos utilizar as personas e histórias de usuários levantadas pelo grupo por meio de entrevistas com possíveis usuários.
75 |
76 | ## Personas e Mapas de Empatia
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | ## Histórias de Usuários
88 |
89 | > Com base na análise das personas forma identificadas as seguintes histórias de usuários:
90 |
91 | |EU COMO... `PERSONA`| QUERO/PRECISO ... `FUNCIONALIDADE` |PARA ... `MOTIVO/VALOR` |
92 | |--------------------|------------------------------------|----------------------------------------|
93 | |Ana Beatriz | criar uma lista com os convidados e o que irão levar | ter conhecimento do que preciso pedir. |
94 | |Ana Beatriz | fazer uma estimativa de custo por convidado em 1 evento | fazer a lista de quantas pessoas vou convidar |
95 | |Maria Lana | reaproveitar o planejamento de um evento | não ter que escrever tudo novamente, e encher meu whatsapp com mensagens desnecessárias. |
96 | |Maria Lana | listar, e lembrar o que falta ser avaliado | não esquecer de algo essencial para o evento. |
97 | |Caio Martins | personalizar os preços médios com gastos do eventos | personalizar os preços médios com gastos do evento ter uma estimativa do custo.|
98 | |Caio Martins | planejar o evento junto de outras pessoas | criar grupos sobre a todo momento é desgastante. |
99 | |Gabriel Chagas | facilidade em adicionar gastos | usar o teclado para fazer tudo cansa. |
100 | |Gabriel Chagas | que outras pessoas saibam do que eu preciso | não gastar meu tempo procurando gente para resolver meu problema. |
101 |
102 | ## Requisitos
103 |
104 | > As tabelas a seguir apresentam os requisitos funcionais e não funcionais que detalham o escopo do projeto.
105 |
106 | ### Requisitos Funcionais
107 |
108 | |ID | Descrição do Requisito | Prioridade |
109 | |------|-----------------------------------------|----|
110 | |RF-001| Possibilitar o usuário de criar listas de participantes para o seu evento | Alta |
111 | |RF-002| Possibilitar o usuário de listar elementos que deseja em seu evento | Alta |
112 | |RF-003| Auxiliar o usuário calcular a quantidade necessária de cada insumo para seu evento | Alta |
113 | |RF-004| Possibilitar o usuário de criar múltiplas demandas para seu evento | Alta |
114 | |RF-005| Permitir que o usuário especifique o que será considerado um gasto em cada evento |Alta|
115 | |RF-006| Estimar o valor de um evento com base nos participantes, insumos e serviços | Alta |
116 | |RF-007| Possibilitar o usuário de compartilhar uma demanda com outros usuários | Média |
117 | |RF-008| Lista de afazeres para auxiliar organização do evento | Média |
118 | |RF-009| Permitir que o usuário seja específico quanto á algum serviço do seu evento | Média |
119 | |RF-010| Recomendar mudanças sobre o planejamento de um evento |Baixa|
120 | |RF-011| Utilizar algum meio para reconhecer o preço médio de um produto (API) |Baixa|
121 | |RF-012| Diferenciar diferentes eventos |Baixa|
122 | |RF-013| Permitir que mais de uma pessoa planeje cada evento |Baixa|
123 | |RF-014| Permitir ao usuário personalizar um elemento em específico de uma lista | Baixa |
124 |
125 |
126 | ### Requisitos não Funcionais
127 |
128 | |ID | Descrição do Requisito |Prioridade |
129 | |-------|-------------------------|----|
130 | |RNF-001| O site deverá ser de intuitivo | Alta |
131 | |RNF-002| Página não deverá ser recarregadada a cada mudança realizada | Alta |
132 | |RNF-003| O site deverá apresentar responsividade | Média |
133 | |RNF-004| Todas as páginas deverão rodar de forma fluída | Baixa |
134 |
135 | ## Restrições
136 |
137 | > Regras eu deverão ser seguidas a risca durante desenvolvimento do projeto
138 |
139 | | ID | Restrição |
140 | | -- |-------------------------------------------------------|
141 | | RE-01 | O projeto deverá ser entregue até o final do semestre. |
142 | | RE-02 | A equipe deverá reportar todo o desenvolvimento no Trello. |
143 | | RE-03 | A equipe não pode subcontratar o desenvolvimento do trabalho. |
144 | | RE-04 | As tecnologias utilizadas devem restringir à HTML, CSS e JavaScript. |
145 |
146 | # Userflow
147 |
148 | > 1° Listas: Organizando entre as categorias Participantes, Insumos, e Serviços, o usuário deve especificar quais elementos existirão para aquele evento
149 |
150 | 
151 |
152 | > 2° Fluxo: Usuário criará relações entre as listas de particpantes e os elementos das listas de Insumos
153 |
154 | 
155 |
156 | > 3° Chamados: Usuário compartilhará sua demanda e valor que está disposto a pagar por ela, sendo contactado por aqueles interessados em supri-la
157 |
158 | 
159 |
160 | > 4° Coleção: Usuário terá uma visão geral sobre os elementos de seu evento
161 |
162 | 
163 |
164 | > 5° Valores: Com os dados já coletados, dá uma estimativa de quanto o evento custará, e disponibilizará gráficos onde serão mostrados proporcionalidades de cada categoria
165 |
166 | 
167 |
168 | # Metodologia
169 |
170 | Neste contexto, o grupo optou por utilizar o framework Scrum para o desenvolvimento do projeto, visto que o mesmo é um framework ágil que permite a adaptação do processo de desenvolvimento de acordo com as necessidades do projeto.
171 |
172 | ## Ferramentas
173 |
174 | | Ambiente | Plataforma |Link de Acesso |
175 | |-----------|-------------------------|---------------|
176 | | Documentação | Google Docs | https://docs.google.com/document/d/1qjGNgSORIWJKUIP3m1bH0Y8Otmr99sSKhRu7RO_rozI/edit?usp=sharing |
177 | | Weekly Scrum | Discord | https://discord.gg/QcnfPCfZ |
178 | | Backlog | Trello | https://trello.com/invite/b/IRT28t7u/ATTIa9c7c509f0e7eaf3ac96967fc2edecff66B9AE32/event-manager |
179 | | Código fonte | GitHub | https://github.com/ICEI-PUC-Minas-PMGES-TI/pmg-es-2023-1-ti1-2401100-quantofica |
180 | |~~Hospedagem do site~~ | ~~Heroku~~ | ~~https://event-manager-tiaw-e7211e805cd0.herokuapp.com~~|
181 | |Hospedagem do site| Vercel | https://event-manager-phi.vercel.app |
182 |
183 |
184 | > ~~Heroku foi escolhido como plataforma de hospedagem por não exigir que o código fonte passe pelo processo de minificação, algo realizado por ferramentas como rollup, webpack, e gulp. Como o código fonte não é minificado, é possível inspeciona-lo apenas com o link de seu deploy.~~
185 |
186 | > Deploy atual no vercel.app utilizando vite
187 |
188 | ## Controle de Versão
189 |
190 | Em nosso repositório existem 3 diferentes branchs, sendo elas:
191 |
192 | * **master**: branch principal, onde se encontra o código fonte da aplicação.
193 | * **novo**: branch onde se encontra o código fonte da aplicação antes de ser reescrito.
194 | * **antigo**: branch onde se encontra a primeira versão da aplicação.
195 |
196 | Para realizar os **commits**, independentemente da **branch** foi utilizado o seguinte padrão:
197 |
198 | `git commit -m "Adicionada funcionalidade x"`
199 |
200 | > Onde a mensagem de commit deverá sempre começar com letra maiúscula e estar conjugada no particípio passado, indicando uma ação já concluída.
201 |
202 | Quanto a gerência de **issues**, o projeto adota a seguinte convenção para etiquetas:
203 |
204 | * `single:` afeta apenas uma funcionalidade
205 | * `multiple:` afeta mais de uma funcionalidade
206 |
207 | > Geralmente, funcionalidades com maior número de issues single, são as geradoras de issues multiple.
208 |
209 | # Projeto da Solução
210 |
211 | Nesta seção do documento será apresentado a solução desenvolvida pelo grupo para o problema apresentado na seção [Introdução](#introdução). Para tanto, será apresentado as tecnologias utilizadas, a arquitetura da solução e a forma como a solução foi desenvolvida.
212 |
213 | ## Tecnologias Utilizadas
214 |
215 | O projeto foi desenvolvido como uma aplicação **Node Vanilla** (HTML, CSS, Javascript), utilizando o **Express** como framework para o servidor, o **localStorage** do próprio navegador como banco de dados, e **Git** para versionamento.
216 |
217 | Bibliotecas utilizadas para para o front-end:
218 | * Bootstrap ( Sistema de grid )
219 | * Bootstrap Icons ( Ícones )
220 | * jQuery ( Programação em JavaScript mais eficiente )
221 | * jQuery UI ( Função draggable() )
222 | * Leader Line ( Cria uma linha entre dois elementos HTML )
223 | * Hero Patterns ( Conjunto de texturas )
224 |
225 | ## Arquitetura da solução (Antigo)
226 |
227 | 
228 |
229 | ### Na imagem acima podemos ver a organização das pastas e o localStorage após um uso simples do site, como o Heroku não aceita personalização da pasta raiz, tive que rodar o sguinte comando para fazer o deploy:
230 |
231 | `git subtree push --prefix codigo heroku master`
232 |
233 | > Onde heroku é a variável que contém o link para o repositório remoto, master é a branch que será enviada, e 'codigo' é a pasta que contém os arquivos da imagem acima.
234 |
235 | # Avaliação da Aplicação
236 |
237 | Nesta parte será abordado as estapas realizadas para verificar se o projeto desenvolvido se adequa nas especificações levantadas na seção [Especificação do Projeto](#especificações-do-projeto).
238 |
239 | ## Plano de Testes
240 |
241 | Primeiramente, pegamos a tabela [histórias de usuário](#histórias-de-usuários), e verificamos se todas as histórias foram atendidas.
242 |
243 | Após isso voltamos na tabela de requisitos, e verificamos se os requisitos foram atendidos fe forma satisfatória.
244 |
245 | Foi realizado planejamanto de eventos reais, visando testar a aplicação em um cenário real, e verificar se ela atendia as necessidades do usuário.
246 |
247 | No final, fizemos um teste de usabilidade com um usuário, para ver se ele conseguia utilizar o site sem dificuldades.
248 |
249 | ## Registros de Testes
250 |
251 | Os testes mostraram que com devida **criatividade** e esforço, é possível sim planejar um evento utilizando o site, sendo alguma das vezes, necessária uma visão um pouco mais abstrata, seria bem vindo templates pré-definidos para simplificar ainda mais o processo.
252 |
253 | # Referências
254 |
255 | ### Sites utilizados no desenvolvimento do projeto:
256 |
257 | * [Chat GPT](https://chat.openai.com)
258 | * [Bootstrap](https://getbootstrap.com)
259 | * [Bootstrap Icons](https://icons.getbootstrap.com)
260 | * [jQuery UI](https://jqueryui.com)
261 | * [Leader Line](https://anseki.github.io/leader-line/)
262 | * [Hero Patterns](https://heropatterns.com)
--------------------------------------------------------------------------------
/codigo/src/Valores.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Event Manager
10 |
11 |
12 |
13 |
14 |
15 |
364 | O máximo de items em uma lista de afazeres é 12.
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution 4.0 International Public License
58 |
59 | By exercising the Licensed Rights (defined below), You accept and agree
60 | to be bound by the terms and conditions of this Creative Commons
61 | Attribution 4.0 International Public License ("Public License"). To the
62 | extent this Public License may be interpreted as a contract, You are
63 | granted the Licensed Rights in consideration of Your acceptance of
64 | these terms and conditions, and the Licensor grants You such rights in
65 | consideration of benefits the Licensor receives from making the
66 | Licensed Material available under these terms and conditions.
67 |
68 |
69 | Section 1 -- Definitions.
70 |
71 | a. Adapted Material means material subject to Copyright and Similar
72 | Rights that is derived from or based upon the Licensed Material
73 | and in which the Licensed Material is translated, altered,
74 | arranged, transformed, or otherwise modified in a manner requiring
75 | permission under the Copyright and Similar Rights held by the
76 | Licensor. For purposes of this Public License, where the Licensed
77 | Material is a musical work, performance, or sound recording,
78 | Adapted Material is always produced where the Licensed Material is
79 | synched in timed relation with a moving image.
80 |
81 | b. Adapter's License means the license You apply to Your Copyright
82 | and Similar Rights in Your contributions to Adapted Material in
83 | accordance with the terms and conditions of this Public License.
84 |
85 | c. Copyright and Similar Rights means copyright and/or similar rights
86 | closely related to copyright including, without limitation,
87 | performance, broadcast, sound recording, and Sui Generis Database
88 | Rights, without regard to how the rights are labeled or
89 | categorized. For purposes of this Public License, the rights
90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
91 | Rights.
92 |
93 | d. Effective Technological Measures means those measures that, in the
94 | absence of proper authority, may not be circumvented under laws
95 | fulfilling obligations under Article 11 of the WIPO Copyright
96 | Treaty adopted on December 20, 1996, and/or similar international
97 | agreements.
98 |
99 | e. Exceptions and Limitations means fair use, fair dealing, and/or
100 | any other exception or limitation to Copyright and Similar Rights
101 | that applies to Your use of the Licensed Material.
102 |
103 | f. Licensed Material means the artistic or literary work, database,
104 | or other material to which the Licensor applied this Public
105 | License.
106 |
107 | g. Licensed Rights means the rights granted to You subject to the
108 | terms and conditions of this Public License, which are limited to
109 | all Copyright and Similar Rights that apply to Your use of the
110 | Licensed Material and that the Licensor has authority to license.
111 |
112 | h. Licensor means the individual(s) or entity(ies) granting rights
113 | under this Public License.
114 |
115 | i. Share means to provide material to the public by any means or
116 | process that requires permission under the Licensed Rights, such
117 | as reproduction, public display, public performance, distribution,
118 | dissemination, communication, or importation, and to make material
119 | available to the public including in ways that members of the
120 | public may access the material from a place and at a time
121 | individually chosen by them.
122 |
123 | j. Sui Generis Database Rights means rights other than copyright
124 | resulting from Directive 96/9/EC of the European Parliament and of
125 | the Council of 11 March 1996 on the legal protection of databases,
126 | as amended and/or succeeded, as well as other essentially
127 | equivalent rights anywhere in the world.
128 |
129 | k. You means the individual or entity exercising the Licensed Rights
130 | under this Public License. Your has a corresponding meaning.
131 |
132 |
133 | Section 2 -- Scope.
134 |
135 | a. License grant.
136 |
137 | 1. Subject to the terms and conditions of this Public License,
138 | the Licensor hereby grants You a worldwide, royalty-free,
139 | non-sublicensable, non-exclusive, irrevocable license to
140 | exercise the Licensed Rights in the Licensed Material to:
141 |
142 | a. reproduce and Share the Licensed Material, in whole or
143 | in part; and
144 |
145 | b. produce, reproduce, and Share Adapted Material.
146 |
147 | 2. Exceptions and Limitations. For the avoidance of doubt, where
148 | Exceptions and Limitations apply to Your use, this Public
149 | License does not apply, and You do not need to comply with
150 | its terms and conditions.
151 |
152 | 3. Term. The term of this Public License is specified in Section
153 | 6(a).
154 |
155 | 4. Media and formats; technical modifications allowed. The
156 | Licensor authorizes You to exercise the Licensed Rights in
157 | all media and formats whether now known or hereafter created,
158 | and to make technical modifications necessary to do so. The
159 | Licensor waives and/or agrees not to assert any right or
160 | authority to forbid You from making technical modifications
161 | necessary to exercise the Licensed Rights, including
162 | technical modifications necessary to circumvent Effective
163 | Technological Measures. For purposes of this Public License,
164 | simply making modifications authorized by this Section 2(a)
165 | (4) never produces Adapted Material.
166 |
167 | 5. Downstream recipients.
168 |
169 | a. Offer from the Licensor -- Licensed Material. Every
170 | recipient of the Licensed Material automatically
171 | receives an offer from the Licensor to exercise the
172 | Licensed Rights under the terms and conditions of this
173 | Public License.
174 |
175 | b. No downstream restrictions. You may not offer or impose
176 | any additional or different terms or conditions on, or
177 | apply any Effective Technological Measures to, the
178 | Licensed Material if doing so restricts exercise of the
179 | Licensed Rights by any recipient of the Licensed
180 | Material.
181 |
182 | 6. No endorsement. Nothing in this Public License constitutes or
183 | may be construed as permission to assert or imply that You
184 | are, or that Your use of the Licensed Material is, connected
185 | with, or sponsored, endorsed, or granted official status by,
186 | the Licensor or others designated to receive attribution as
187 | provided in Section 3(a)(1)(A)(i).
188 |
189 | b. Other rights.
190 |
191 | 1. Moral rights, such as the right of integrity, are not
192 | licensed under this Public License, nor are publicity,
193 | privacy, and/or other similar personality rights; however, to
194 | the extent possible, the Licensor waives and/or agrees not to
195 | assert any such rights held by the Licensor to the limited
196 | extent necessary to allow You to exercise the Licensed
197 | Rights, but not otherwise.
198 |
199 | 2. Patent and trademark rights are not licensed under this
200 | Public License.
201 |
202 | 3. To the extent possible, the Licensor waives any right to
203 | collect royalties from You for the exercise of the Licensed
204 | Rights, whether directly or through a collecting society
205 | under any voluntary or waivable statutory or compulsory
206 | licensing scheme. In all other cases the Licensor expressly
207 | reserves any right to collect such royalties.
208 |
209 |
210 | Section 3 -- License Conditions.
211 |
212 | Your exercise of the Licensed Rights is expressly made subject to the
213 | following conditions.
214 |
215 | a. Attribution.
216 |
217 | 1. If You Share the Licensed Material (including in modified
218 | form), You must:
219 |
220 | a. retain the following if it is supplied by the Licensor
221 | with the Licensed Material:
222 |
223 | i. identification of the creator(s) of the Licensed
224 | Material and any others designated to receive
225 | attribution, in any reasonable manner requested by
226 | the Licensor (including by pseudonym if
227 | designated);
228 |
229 | ii. a copyright notice;
230 |
231 | iii. a notice that refers to this Public License;
232 |
233 | iv. a notice that refers to the disclaimer of
234 | warranties;
235 |
236 | v. a URI or hyperlink to the Licensed Material to the
237 | extent reasonably practicable;
238 |
239 | b. indicate if You modified the Licensed Material and
240 | retain an indication of any previous modifications; and
241 |
242 | c. indicate the Licensed Material is licensed under this
243 | Public License, and include the text of, or the URI or
244 | hyperlink to, this Public License.
245 |
246 | 2. You may satisfy the conditions in Section 3(a)(1) in any
247 | reasonable manner based on the medium, means, and context in
248 | which You Share the Licensed Material. For example, it may be
249 | reasonable to satisfy the conditions by providing a URI or
250 | hyperlink to a resource that includes the required
251 | information.
252 |
253 | 3. If requested by the Licensor, You must remove any of the
254 | information required by Section 3(a)(1)(A) to the extent
255 | reasonably practicable.
256 |
257 | 4. If You Share Adapted Material You produce, the Adapter's
258 | License You apply must not prevent recipients of the Adapted
259 | Material from complying with this Public License.
260 |
261 |
262 | Section 4 -- Sui Generis Database Rights.
263 |
264 | Where the Licensed Rights include Sui Generis Database Rights that
265 | apply to Your use of the Licensed Material:
266 |
267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
268 | to extract, reuse, reproduce, and Share all or a substantial
269 | portion of the contents of the database;
270 |
271 | b. if You include all or a substantial portion of the database
272 | contents in a database in which You have Sui Generis Database
273 | Rights, then the database in which You have Sui Generis Database
274 | Rights (but not its individual contents) is Adapted Material; and
275 |
276 | c. You must comply with the conditions in Section 3(a) if You Share
277 | all or a substantial portion of the contents of the database.
278 |
279 | For the avoidance of doubt, this Section 4 supplements and does not
280 | replace Your obligations under this Public License where the Licensed
281 | Rights include other Copyright and Similar Rights.
282 |
283 |
284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
285 |
286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
296 |
297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
306 |
307 | c. The disclaimer of warranties and limitation of liability provided
308 | above shall be interpreted in a manner that, to the extent
309 | possible, most closely approximates an absolute disclaimer and
310 | waiver of all liability.
311 |
312 |
313 | Section 6 -- Term and Termination.
314 |
315 | a. This Public License applies for the term of the Copyright and
316 | Similar Rights licensed here. However, if You fail to comply with
317 | this Public License, then Your rights under this Public License
318 | terminate automatically.
319 |
320 | b. Where Your right to use the Licensed Material has terminated under
321 | Section 6(a), it reinstates:
322 |
323 | 1. automatically as of the date the violation is cured, provided
324 | it is cured within 30 days of Your discovery of the
325 | violation; or
326 |
327 | 2. upon express reinstatement by the Licensor.
328 |
329 | For the avoidance of doubt, this Section 6(b) does not affect any
330 | right the Licensor may have to seek remedies for Your violations
331 | of this Public License.
332 |
333 | c. For the avoidance of doubt, the Licensor may also offer the
334 | Licensed Material under separate terms or conditions or stop
335 | distributing the Licensed Material at any time; however, doing so
336 | will not terminate this Public License.
337 |
338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
339 | License.
340 |
341 |
342 | Section 7 -- Other Terms and Conditions.
343 |
344 | a. The Licensor shall not be bound by any additional or different
345 | terms or conditions communicated by You unless expressly agreed.
346 |
347 | b. Any arrangements, understandings, or agreements regarding the
348 | Licensed Material not stated herein are separate from and
349 | independent of the terms and conditions of this Public License.
350 |
351 |
352 | Section 8 -- Interpretation.
353 |
354 | a. For the avoidance of doubt, this Public License does not, and
355 | shall not be interpreted to, reduce, limit, restrict, or impose
356 | conditions on any use of the Licensed Material that could lawfully
357 | be made without permission under this Public License.
358 |
359 | b. To the extent possible, if any provision of this Public License is
360 | deemed unenforceable, it shall be automatically reformed to the
361 | minimum extent necessary to make it enforceable. If the provision
362 | cannot be reformed, it shall be severed from this Public License
363 | without affecting the enforceability of the remaining terms and
364 | conditions.
365 |
366 | c. No term or condition of this Public License will be waived and no
367 | failure to comply consented to unless expressly agreed to by the
368 | Licensor.
369 |
370 | d. Nothing in this Public License constitutes or may be interpreted
371 | as a limitation upon, or waiver of, any privileges and immunities
372 | that apply to the Licensor or You, including from the legal
373 | processes of any jurisdiction or authority.
374 |
375 |
376 | =======================================================================
377 |
378 | Creative Commons is not a party to its public
379 | licenses. Notwithstanding, Creative Commons may elect to apply one of
380 | its public licenses to material it publishes and in those instances
381 | will be considered the “Licensor.” The text of the Creative Commons
382 | public licenses is dedicated to the public domain under the CC0 Public
383 | Domain Dedication. Except for the limited purpose of indicating that
384 | material is shared under a Creative Commons public license or as
385 | otherwise permitted by the Creative Commons policies published at
386 | creativecommons.org/policies, Creative Commons does not authorize the
387 | use of the trademark "Creative Commons" or any other trademark or logo
388 | of Creative Commons without its prior written consent including,
389 | without limitation, in connection with any unauthorized modifications
390 | to any of its public licenses or any other arrangements,
391 | understandings, or agreements concerning use of licensed material. For
392 | the avoidance of doubt, this paragraph does not form part of the
393 | public licenses.
394 |
395 | Creative Commons may be contacted at creativecommons.org.
396 |
--------------------------------------------------------------------------------
/codigo/src/Collection.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Event Manager
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
96 |
97 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
196 |
197 |
198 |
199 |
200 |
201 |
Leonardo
202 |
Giovanna
203 |
Gabriel
204 |
Alice
205 |
Vitor
206 |
Mateus
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
218 |
219 |
220 |
221 |
222 |
223 |
Alana
224 |
Isabel
225 |
Carol
226 |
Lara
227 |
Vitor
228 |
Mateus
229 |
Alana
230 |
Isabel
231 |
Carol
232 |
Lara
233 |
Vitor
234 |
Mateus
235 |
Alana
236 |
Isabel
237 |
Carol
238 |
Lara
239 |
Vitor
240 |
Mateus
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
252 |
253 |
254 |
255 |
256 |
257 |
Leonardo
258 |
Giovanna
259 |
Gabriel
260 |
Alice
261 |
Vitor
262 |
Mateus
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
279 |
280 |
281 |
282 |
283 |
284 |
287 |
288 |
289 |
290 |
291 |
Negrinni
292 |
Gin
293 |
Aperol
294 |
Moscow Mule
295 |
Caipirinha
296 |
Pina Colada
297 |
298 |
299 |
300 |
301 |
302 |
303 |
306 |
307 |
308 |
309 |
310 |
Macarrão
311 |
Raviolli
312 |
Risotto
313 |
314 |
315 |
316 |
317 |
318 |
319 |
322 |
323 |
324 |
325 |
326 |
Chinelo
327 |
Pulseira
328 |
Óculos
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
355 |
356 |
357 |
358 |
359 |
360 | Fotógrafo
361 | R$4.000,00
362 |
363 |
364 | Maquiadora
365 | R$690,00
366 |
367 |
368 | Vestidos
369 | R$3.900,00
370 |
371 |
373 | Design
374 | R$1.500,00
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
385 |
386 |
387 |
388 |
389 |
390 | DJ
391 | R$2.000,00
392 |
393 |
394 | Ceriomônia
395 | R$1.000,00
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
Abrir um chamado para Design
411 |
412 |
413 |
414 |
424 |
425 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
--------------------------------------------------------------------------------
/codigo/src/JS/cardMovivel.js:
--------------------------------------------------------------------------------
1 | /*
2 | ? Documentação:
3 | carregaCards() - Carrega os cards salvos no localStorage quando a página é carregada
4 | nomeiaCard(element) - Botão que edita o título do card
5 | resetaCard(element) - Botão que reseta o conteúdo do card
6 | removeCard(element) - Botão que apaga o card
7 | finalDaLinha(element) - Cursor no final de cada linha
8 | removerLiVazias(cardContainer) - Remove li vazias
9 | atualizaTitulo(element) - Atualiza o título do card
10 | atualizaConteudo(element) - Atualiza conteudo do card
11 | isTextSelected(element) - Permite alterar o título caso conteúdo esteja inteiramente selecionados
12 | customDrag(elemento) - Função para configurar regras para movimentação do card
13 | editaCard(element) - Editar o conteúdo do card quando clicar em alguma linha
14 | selectAll(element) - Permite selecionar todo o texto de um elemento
15 | criaConteudo(lista, gapping) - HTML de um card
16 | */
17 | // ? Mesmo não havendo caracteres menores que 2.5 pixels, é bom definir uma margem de segurança
18 | // ? Seria possível colocar infinitos caracteres de largura 0
19 | // ? estéticamente não teria efeito algum, porém travaria o programa
20 |
21 | // * Objeto que guarda as informações de cada card (Objeto do tipo Lista)
22 |
23 | import './bootstrap.js';
24 | import 'jquery-ui-dist/jquery-ui';
25 | import * as bootstrap from 'bootstrap';
26 |
27 | class Lista {
28 | constructor(_id, titulo, linhas, coordenadas) {
29 | this._id = _id;
30 | this.titulo = titulo;
31 | this.linhas = linhas;
32 | this.coordenadas = coordenadas;
33 | }
34 | }
35 | var maxWidth = 200; // * Máximo de pixels permitidos no título
36 | var maxLength = 100; // * Máximo de caracteres permitidos no título
37 | const TAM = 6; // * Quantidade de cards que será possível adicionar
38 |
39 | var elemento = "elementosParticipantes"; // * Para manipular listas de uma determinada careogoria
40 |
41 | var vetor = Array(TAM).fill(true); // * True = Disponível, False = Ocupado
42 | var matriz = [];
43 | for (var i = 0; i < 3; i++) {
44 | matriz.push(Array(TAM).fill(true));
45 | }
46 |
47 | // * Pegará do local Storage para deixar salvo quando a página recarregar
48 | var ListaTipo = localStorage.getItem("ultimaLista") || "ListaParticipantes";
49 |
50 | var position = 0;
51 | var todasListas = [];
52 |
53 | if (ListaTipo === "ListaParticipantes") {
54 | $('.listaParticipantes').addClass('active');
55 | $('.listaInsumos, .listaServicos').removeClass('active');
56 | position = 0;
57 | elemento = "elementosParticipantes";
58 | carregaCards();
59 | }
60 | if (ListaTipo === "ListaInsumos") {
61 | $('.listaInsumos').addClass('active');
62 | $('.listaParticipantes, .listaServicos').removeClass('active');
63 | position = 1;
64 | elemento = "elementosInsumos";
65 | carregaCards();
66 | }
67 | if (ListaTipo === "ListaServicos") {
68 | $('.listaServicos').addClass('active');
69 | $('.listaParticipantes, .listaInsumos').removeClass('active');
70 | position = 2;
71 | elemento = "elementosServicos"; // > Provavelmente não será necessário
72 | carregaCards();
73 | }
74 |
75 | // * Carrega os cards salvos no localStorage quando a página é carregada
76 | function carregaCards() {
77 | // * Limpa todos os cards
78 | $('.card').parent().remove();
79 | todasListas = JSON.parse(localStorage.getItem(ListaTipo)); // * Pega todas as listas salvas no localStorage
80 | if (todasListas) { // ? Caso não exista nada no localStorage, todasListas será null e não entrará no if
81 | let cont = 0; // * Contador para definir a posição dos cards
82 | for (let i = 0; i < TAM; i++) {
83 | // * Caso não exista nenhuma informação salva naquela posição, não será criado o card
84 | if (todasListas[i] != null) {
85 |
86 | // * Cria um objeto do tipo Lista com as informações do objeto salvo no localStorage
87 | let lista = new Lista(todasListas[i]._id, todasListas[i].titulo, todasListas[i].linhas, todasListas[i].coordenadas);
88 | // * Cria o card com as informações do objeto
89 | let carregaCard = criaConteudo(lista, cont++);
90 |
91 | // ? É como se estivessemos adicionando funcionalidades que um card é capaz de fazer
92 | customDrag(carregaCard);
93 | editaCard(carregaCard);
94 | nomeiaCard(carregaCard);
95 | resetaCard(carregaCard);
96 | removeCard(carregaCard);
97 |
98 | $('section').append(carregaCard); // * Adiciona o card na página
99 | matriz[position][i] = false; // * Posição ocupada
100 | } else { matriz[position][i] = true; console.log("entrou") } // * Posição disponível
101 | }
102 | } else { todasListas = []; }
103 | }
104 | // * Botões só estarão disponíveis após o carregamento da página
105 | $(document).ready(() => {
106 | carregaCards();
107 |
108 | $('#adicionaCard').click(() => {
109 | let indiceTrue = -1;
110 | for (var i = 0; i < TAM; i++) {
111 | if (matriz[position][i] === true) {
112 | matriz[position][i] = false;
113 | indiceTrue = i;
114 | break;
115 | }
116 | }
117 |
118 | // * Percorre o vetor, se existir algum elemento com o valor true, criará card
119 | if (indiceTrue === -1) {
120 | $('.toast-body').text('O Número máximo de cards para esta categoria foi atingido.');
121 | $('.toast').toast('show');
122 | return;
123 | }
124 |
125 | // * Realizar testes para checar se foi corrigido
126 | var lista = new Lista(indiceTrue, 'Lista ' + (indiceTrue + 1), " ", null);
127 | var newCard = criaConteudo(lista, indiceTrue);
128 |
129 | customDrag(newCard);
130 | editaCard(newCard);
131 | nomeiaCard(newCard);
132 | resetaCard(newCard);
133 | removeCard(newCard);
134 |
135 | todasListas[indiceTrue] = lista;
136 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
137 |
138 | $('section').append(newCard);
139 | });
140 | // > Nome poderia ser removeTodosCards
141 | $('#removeCard').click(() => {
142 | $('.card').parent().remove();
143 | matriz[position].fill(true); // * Todas as posições se tornam disponíveis
144 | todasListas = []; // * Agora o vetor é vazio
145 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
146 |
147 | let elementoApagados = JSON.parse(localStorage.getItem(elemento)) || [];
148 | elementoApagados.fill(null);
149 | localStorage.setItem(elemento, JSON.stringify(elementoApagados));
150 | });
151 | $('#organizaCard').click(() => {
152 | // > Não acho que precisa mas bora deixar aqui
153 | todasListas = JSON.parse(localStorage.getItem(ListaTipo));
154 | for (let i = 0; i < todasListas.length; i++) {
155 | if (todasListas[i] != null) {
156 | todasListas[i].coordenadas = null;
157 | }
158 | }
159 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
160 | carregaCards();
161 | });
162 | $('.listaParticipantes').click(() => {
163 | $('#tipoLista').find('i').removeClass('bi-cash-stack bi-briefcase').addClass('bi-people');
164 | $('#tipoLista').find('span').text('Participantes');
165 | $('.listaParticipantes').addClass('active');
166 | $('.listaInsumos, .listaServicos').removeClass('active');
167 | ListaTipo = "ListaParticipantes";
168 | elemento = "elementosServicos";
169 | localStorage.setItem("ultimaLista", ListaTipo);
170 | position = 0;
171 | localStorage.setItem("ultimaListaPosicao", position);
172 | carregaCards();
173 | });
174 | $('.listaInsumos').click(() => {
175 | $('#tipoLista').find('i').removeClass('bi-people bi-briefcase').addClass('bi-cash-stack');
176 | $('#tipoLista').find('span').text('Insumos');
177 | $('.listaInsumos').addClass('active');
178 | $('.listaParticipantes, .listaServicos').removeClass('active');
179 | ListaTipo = "ListaInsumos";
180 | elemento = "elementosInsumos";
181 | localStorage.setItem("ultimaLista", ListaTipo);
182 | position = 1;
183 | localStorage.setItem("ultimaListaPosicao", position);
184 | carregaCards();
185 | });
186 | $('.listaServicos').click(() => {
187 | $('#tipoLista').find('i').removeClass('bi-people bi-cash-stack').addClass('bi-briefcase');
188 | $('#tipoLista').find('span').text('Serviços');
189 | $('.listaServicos').addClass('active');
190 | $('.listaParticipantes, .listaInsumos').removeClass('active');
191 | ListaTipo = "ListaServicos";
192 | localStorage.setItem("ultimaLista", ListaTipo);
193 | elemento = "elementosServicos"; // > Provavelmente não será necessário
194 | position = 2;
195 | localStorage.setItem("ultimaListaPosicao", position);
196 | carregaCards();
197 | });
198 | });
199 | // * Botão que edita o título do card
200 | function nomeiaCard(element) {
201 | element.find('.nomeiaCard').click(function () {
202 | // * Seleciona o título, permite edição, foca nele, e seleciona todo o texto
203 | let cardTitle = $(this).closest('.card-container').find('.card-header span:first-child');
204 | cardTitle.attr('contenteditable', 'true');
205 | cardTitle.focus();
206 | selectAll(cardTitle[0]);
207 | // * Ao editar o título, outros cards se tornam fixos
208 | $('.card-container').not($(this).closest('.card-container')).css('position', 'fixed');
209 |
210 | // * Cards em edição tem z-index maior que os outros
211 | $(this).closest('.card-container').css('z-index', '1');
212 | $('.card-container').not($(this).closest('.card-container')).css('z-index', '0');
213 |
214 | // * Ao perder o foco, o título é alterado
215 | cardTitle.blur(function () {
216 | atualizaTitulo($(this));
217 | });
218 | // * Ao pressionar enter, o título é alterado
219 | cardTitle.on('keydown click', function (e) {
220 | if (e.keyCode === 13) {
221 | e.preventDefault();
222 | atualizaTitulo($(this));
223 | cardTitle.attr('contenteditable', 'false');
224 | let listGroup = $(this).closest('.card-container').find('.list-group');
225 | let lastLi = listGroup.find('li:last-child').focus();
226 | finalDaLinha(lastLi[0]);
227 | } else if (($(this).width() >= maxWidth || $(this).text().length >= maxLength) && !isTextSelected(cardTitle[0])
228 | && e.keyCode !== 8 && e.keyCode !== 46 && e.keyCode !== 37 && e.keyCode !== 39 && !e.ctrlKey) {
229 | // * Impede que o usuário digite mais caracteres que o permitido
230 | e.preventDefault();
231 | $('.toast-body').text('Tamanho máximo de título atingido.');
232 | $('.toast').toast('show');
233 | }
234 | // * Caso o usuário consiga digitar mais caracteres que o permitido, o título é cortado
235 | if ($(this).text().length > maxLength) {
236 | let trimmedText = $(this).text().substring(0, maxLength);
237 | cardTitle.text(trimmedText);
238 | }
239 | });
240 | });
241 | }
242 | // * Botão que reseta o conteúdo do card
243 | function resetaCard(element) {
244 | element.find('.resetaCard').click(function () {
245 | $(this).closest('.card-container').find('.list-group li').remove();
246 | let liVazia = $('').text("");
247 | $(this).closest('.card-container').find('.list-group').append(liVazia);
248 | liVazia.focus();
249 |
250 | let cardId = $(this).closest('.card-container').attr('id');
251 | let cardNumber = parseInt(cardId.split('-')[1]);
252 | todasListas[cardNumber].linhas = [];
253 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
254 | });
255 | }
256 | // * Botão que apaga o card
257 | function removeCard(element) {
258 | element.find('.removeCard').click(function () {
259 | let cardId = $(this).closest('.card-container').attr('id');
260 | let cardNumber = parseInt(cardId.split('-')[1]);
261 | $(this).closest('.card-container').remove();
262 | todasListas[cardNumber] = null;
263 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
264 | matriz[position][cardNumber] = true;
265 |
266 | let elementoApagado = JSON.parse(localStorage.getItem(elemento)) || [];
267 | elementoApagado[cardNumber].coordenadas = null;
268 | localStorage.setItem(elemento, JSON.stringify(elementoApagado));
269 | });
270 | }
271 | // * Cursor no final de cada linha
272 | function finalDaLinha(element) {
273 | if (element && element.childNodes && element.childNodes.length > 0) {
274 | let range = document.createRange();
275 | let sel = window.getSelection();
276 | range.setStart(element.childNodes[0], element.childNodes[0].length);
277 | range.collapse(true);
278 | sel.removeAllRanges();
279 | sel.addRange(range);
280 | }
281 | }
282 | // * Remove li vazias
283 | function removerLiVazias(cardContainer) {
284 | cardContainer.find('.list-group-item').each(function () {
285 | // * Vai remover todos os espaços em branco, e checar se ainda resta alguma coisa
286 | if ($(this).text().trim() === '' && cardContainer.find('.list-group-item').length > 1) {
287 | $(this).remove();
288 | atualizaConteudo(cardContainer);
289 | }
290 | });
291 | }
292 | // * Atualiza o título do card
293 | function atualizaTitulo(element) {
294 | let novoNome = element.text().trim();
295 | if (novoNome !== '') {
296 | element.text(novoNome);
297 | let cardId = element.closest('.card-container').attr('id');
298 | let cardNumber = parseInt(cardId.split('-')[1]);
299 | todasListas[cardNumber].titulo = novoNome;
300 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
301 | }
302 | }
303 | // * Atualiza conteudo do card
304 | function atualizaConteudo(element) {
305 | let novoConteudo = [];
306 | element.find('.list-group-item').each(function () {
307 | novoConteudo.push($(this).text().trim());
308 | });
309 | let cardId = element.closest('.card-container').attr('id');
310 | if (cardId != null) {
311 | let cardNumber = parseInt(cardId.split('-')[1]);
312 | todasListas[cardNumber].linhas = novoConteudo;
313 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
314 | console.log('Conteúdo salvo no card de ID ' + cardNumber + ' como: ' + novoConteudo);
315 | }
316 | }
317 | // * Permite alterar o título caso conteúdo esteja inteiramente selecionado
318 | function isTextSelected(element) {
319 | let selection = window.getSelection();
320 | let selectedText = selection.toString();
321 | let elementText = element.textContent;
322 | return selectedText === elementText;
323 | }
324 | // * Função para configurar regras para movimentação do card
325 | function customDrag(elemento) {
326 | elemento.find(".draggable").draggable({
327 | containment: "section",
328 | scroll: false,
329 | snap: false,
330 | stack: ".draggable",
331 | cursor: "grabbing",
332 | handle: ".card-header",
333 | stop: function () { // * Executado sempre que o card é solto
334 | $(this).closest('.card-container').css('position', 'absolute');
335 | // var cardPosition = $(this).position().left + 48 + 300;
336 | // var canvasWidth = $('section').width();
337 | // if (!$('aside').hasClass('active')) {
338 | // larguraPermitida = canvasWidth - 250;
339 | // if (cardPosition > larguraPermitida && !$(this).hasClass('mover')) {
340 | // $(this).addClass('mover');
341 | // console.log('Mover adicionado');
342 | // $(this).find('.card-header').css('background-color', '#f0f0f0');
343 | // } else if (cardPosition <= larguraPermitida && $(this).hasClass('mover')) {
344 | // $(this).removeClass('mover');
345 | // console.log("Mover removido");
346 | // $(this).find('.card-header').css('background-color', '#fff');
347 | // }
348 | // }
349 |
350 | // * Quero pegar as coordanadas do card quando ele for solto
351 | // * E salvar no localStorage
352 | // * E quando a página for carregada, os cards serão carregados com as coordenadas salvas
353 | // * E quando um card for movido, as coordenadas serão atualizadas
354 | // * E quando um card for apagado, as coordenadas serão apagadas
355 |
356 | let cardId = $(this).closest('.card-container').attr('id');
357 | let cardNumber = parseInt(cardId.split('-')[1]);
358 | todasListas[cardNumber].coordenadas = [$(this).offset().left - 48, $(this).offset().top];
359 | localStorage.setItem(ListaTipo, JSON.stringify(todasListas));
360 | console.log('Coordenadas salvas no card de ID ' + cardNumber + ' como: ' + todasListas[cardNumber].coordenadas);
361 | }
362 | });
363 | }
364 | // * Editar o conteúdo do card quando clicar em alguma linha
365 | function editaCard(element) {
366 | element.find('.list-group').on('keydown', function (e) {
367 | // ? Apenas para simplificar o código
368 | let listGroup = $(this).closest('.card-container').find('.list-group');
369 | let otherCards = $('.card-container').not($(this).closest('.card-container'));
370 | let currentLi = listGroup.find('li:focus');
371 | // * Ao perder o foco, o conteúdo é atualizado
372 | listGroup.on('blur', 'li', function () {
373 | atualizaConteudo(listGroup);
374 | });
375 | // * Se o usuário pressionar backspace e a linha estiver vazia, e não houver apenas 1 linha, linha atual é apagada, e o focus irá para a linha anterior
376 | if ((e.keyCode === 8 || e.keyCode === 38 || e.keyCode === 40) && currentLi.text() === '' && listGroup.children().length > 1) {
377 | e.preventDefault();
378 | currentLi.remove();
379 | var lastLi = listGroup.find('li:last-child').focus();
380 | finalDaLinha(lastLi[0]);
381 | }
382 | // * Usuário não pode criar nova linha se atual estiver em branco
383 | if (e.keyCode === 13 && currentLi.text() === '') {
384 | e.preventDefault();
385 | return;
386 | }
387 | // * Enter
388 | if (e.keyCode === 13) {
389 | e.preventDefault();
390 | let liVazia = $('').text("");
391 | otherCards.css('position', 'fixed');
392 | listGroup.append(liVazia);
393 | liVazia.focus();
394 | finalDaLinha(liVazia[0]);
395 | atualizaConteudo($(this).closest('.card-container'));
396 | }
397 | // * Seta para cima
398 | if (e.keyCode === 38) {
399 | e.preventDefault();
400 | currentLi.prev().focus();
401 | finalDaLinha(currentLi.prev()[0]);
402 | }
403 | // * Seta para baixo
404 | if (e.keyCode === 40) {
405 | e.preventDefault();
406 | currentLi.next().focus();
407 | finalDaLinha(currentLi.next()[0]);
408 | }
409 | // * Remove li vazias quando um click é realizado
410 | $(document).click(function () {
411 | // > Aqui possívelmente está gastando mais processamento que o necessário
412 | $('.card-container').each(function () {
413 | removerLiVazias($(this));
414 | });
415 | atualizaConteudo($(this).closest('.card-container'));
416 | });
417 | });
418 | }
419 | // * Permite selecionar todo o texto de um elemento
420 | function selectAll(element) {
421 | if (document.body.createTextRange) { // Suporte para Internet Explorer
422 | var range = document.body.createTextRange();
423 | range.moveToElementText(element);
424 | range.select();
425 | } else if (window.getSelection) { // Suporte para navegadores modernos
426 | var range = document.createRange();
427 | range.selectNodeContents(element);
428 | var selection = window.getSelection();
429 | selection.removeAllRanges();
430 | selection.addRange(range);
431 | }
432 | }
433 | // * HTML de um card
434 | function criaConteudo(lista, gapping) {
435 | var conteudo = '';
436 | if (lista.linhas.length !== 0 && lista.linhas[0] !== '') {
437 | conteudo = '';
438 | for (let i = 0; i < lista.linhas.length; i++) {
439 | // * Caso a linha não seja vazia, ela é adicionada ao conteúdo
440 | if (lista.linhas[i] !== '') {
441 | conteudo += '
`);
521 | }
522 | // * Elemento será uma lista do tipo Insumo
523 | function criaConexao(idP, element) {
524 | let opcoes = '';
525 | if (element.linhas.length > 1 || element.linhas[0].trim() != '') {
526 | element.linhas.forEach((linha) => {
527 | linha = linha.substring(0, 30);
528 | opcoes += ``;
529 | });
530 | }
531 | let parametros = '';
532 | for (let i = 0; i < conexoes[idP][element._id][1].length; i++) { // * Preciso da quantidade de parametros e ID de cada um deles
533 | parametros += `
534 |
557 | `);
558 | }
559 | // * Função que cria o conteúdo HTML do parametro de uma conexão
560 | function criaParametro(i, element) {
561 | let opcoes = '';
562 | if (element.linhas.length > 1) {
563 | element.linhas.forEach((linha) => {
564 | linha = linha.substring(0, 30);
565 | opcoes += ``;
566 | });
567 | }
568 | return `
569 |
570 |
571 |
572 |
575 |
576 |
580 |
`;
581 | }
582 | // * Função para setar os valores da conexão
583 | function recalculaValor(idDestino, insumosAlterado) { // Vai recber o id dos insumos e qual elemento da lista foi alterado
584 | if (elementosInsumos[idDestino].linhas[0].trim() == 0) { return; }
585 | // > Acredito que tenha formas mais simples de fazer isso, revisarei o código caso tenha tempo
586 | console.log("Quantidade de parametros da conexao", insumosAlterado.length);
587 |
588 | let dicionario = {};
589 | for (let i = 0; i < elementosInsumos[idDestino].linhas.length; i++) {
590 | let linha = elementosInsumos[idDestino].linhas[i];
591 | linha = linha.substring(0, 30);
592 | dicionario[linha] = 0;
593 | }
594 |
595 | for (let i = 0; i < TAM; i++) {
596 | if (conexoes[i][idDestino][0] != null) {
597 | for (let j = 0; j < conexoes[i][idDestino][1].length; j++) { // Para parametro da conexao
598 | let insumo = conexoes[i][idDestino][1][j].insumo;
599 | let quantidade = conexoes[i][idDestino][1][j].quantidade * elementosParticipantes[i].linhas.length;
600 | dicionario[insumo] += quantidade;
601 | }
602 | }
603 | }
604 |
605 | // > Agora que tenho o dicionario, irei atualizar os valores
606 | for (let i = 0; i < elementosInsumos[idDestino].linhas.length; i++) {
607 | let linha = elementosInsumos[idDestino].linhas[i];
608 | let quantidade = Math.ceil(dicionario[linha]);
609 | $(`#${idDestino}-${i}`).find('.quantidadeInsumo').text(quantidade);
610 | }
611 |
612 | let dados = "dicionario-" + elementosInsumos[idDestino].titulo;
613 |
614 | // * Preciso salvar no localStorage o dicionario
615 | localStorage.setItem(dados, JSON.stringify(dicionario));
616 | }
617 | // > Selection estilizado (não finalizado ainda)
618 | // > Para funcionar tem que ser passado por dentro do card
619 | $('.select-icon').click(function () {
620 | $(this).siblings('select').trigger('click');
621 | });
622 | //