Giter Club home page Giter Club logo

fct-app's Introduction

Warning

Leia as discussões sobre migrar do Firebase para uma hospedagem própria (#182) antes de desenvolver um recurso novo.

FCT App

O "FCT App" facilita a vida dos alunos da FCT, com o acesso aos eventos do câmpus. Tem alto potencial de expansão.

Contribuindo

Todos podem contribuir para o "FCT App".

Leia o guia de contribuição do CACiC.

Documentação

A documentação do projeto está disponível em cacic-fct/fct-app-docs.

Site

O aplicativo é construído com Angular e pode ser acessado em fct-pp.web.app.

Desenvolvimento

Para iniciar o site localmente, primeiro instale o Ionic CLI e o Bun.

Depois, instale as dependências:

bun install

Em seguida, inicie o servidor de desenvolvimento:

ionic serve --ssl

Simulador do Firebase

Instale o Firebase CLI e faça login.

Depois, no diretório do projeto, inicie o emulador com o comando:

firebase emulators:start --project fct-pp --import=./emulator-data --export-on-exit
Cloud Functions

Para testar as Cloud Functions, primeiro altere o diretório para functions:

cd functions

Depois, instale as dependências:

bun install

Em seguida, compile com:

bun build

Não é necessário reiniciar o simulador após compilar.

fct-app's People

Contributors

yudi avatar dependabot[bot] avatar guict avatar willshobwish avatar yingyangtongxue avatar dayatoledo avatar byt01 avatar

Stargazers

Karol Marques avatar Caio Tavares avatar Wéllyson de Lourenço avatar Paulo Sergio avatar Daniel Serezane avatar Igor Pereira avatar João Baptista avatar

Watchers

 avatar Daniel Serezane avatar Igor Pereira avatar

fct-app's Issues

Enviar comprovante de pagamento

Página para o usuário fazer o upload de uma imagem contendo o comprovante de pagamento.
O arquivo deve ser armazenado no Cloud Storage.

Armazenar o arquivo da seguinte maneira:
root/UIDevento/payment-receipts/UIDusuario

Exemplo - Sendo:

  • root a raiz do cloud storage
  • 123456 o UID do evento
  • abcdef o UID do usuário

Resultado: root/123456/payment-receipts/abcdef

Armazene o arquivo sem a extensão (png, jpg, etc).

Armazene o arquivo com o metadado user: UID sendo UID o UID do usuário

A imagem deve ser comprimida.

O pacote ngx-image-compress não aceita os formatos HEIC e HEIF, logo, limite o upload de imagem aos formatos PNG, JPEG e WEBP apenas.
O formulário não deve aceitar os formatos PDF e GIF.

Limite o tamanho do arquivo em 8 MB

Exiba as informações do evento (nome, valor)
Se o evento é pagável por transferência bancária, exiba todas as informações cadastradas (Banco, CPF/CNPJ, conta, chave pix, informações extras, etc).
Caso tenha uma chave Pix cadastrada, exiba o botão "copiar chave pix".

Se o evento não é pagável por transferência bancária, exiba o texto das "informações extras".

A data limite para o pagamento é a data fim das inscrições.

Observando que o Firebase cobra por largura de banda, por operações de download e por operações de upload, não permitir ao usuário que reenvie ou exiba o comprovante.

Listar usuários inscritos em eventos

Página de admin para listar usuários inscritos em eventos normais e grandes eventos e poder alterar os dados da inscrição, ex: minicursos que ele se inscreveu, validade da inscrição

Botão "Mais Detalhes" não funciona na lista de Inscrições

Resumo

O botão "Mais detalhes" da tela de Minhas Inscrições não funciona.
image

Detalhes

Cada clique no botão gera um novo erro no formato do print abaixo. A função causando problemas parece ser getDateFromTimestamp() que tenta acessar um .seconds que não está chegando corretamente.

Logs e anexos

Console ao carregar https://fct-pp.web.app/inscricoes
image

Listar presenças

O coletor de presenças está pronto, mas não existe um local específico para listar as presenças, nem para exporta-las.

As presenças podem ser exportadas num arquivo CSV com o nome do evento, com o seguinte formato:

Nome RA E-mail Data
João 201200000 [email protected] 15/04/2022 - 12:24
Maria 201200001 [email protected] 15/04/2022 - 12:25

Inscrição em eventos

Botão para alunos da Unesp se inscreverem em eventos, substituindo os forms de inscrição.

Validar comprovante de pagamento

Página para exibir os dados do usuário (nome completo, tipo de inscrição e seu preço) e o comprovante de pagamento que ele enviou.

O admin pode aprovar e validar a inscrição ou recusar fornecendo uma justificativa que aparecerá para o usuário.

Depois de incluir e confirmar a justificativa, perguntar se o admin quer encaminha-la ao WhatsApp do usuário. Se sim, redirecionar para um link https://wa.me/ com o celular do usuário e a justificativa já preenchida.
O celular pode ser obtido no Firestore em users/UID no campo phone, com o formato XX XXXXX-XXXX

Ao validar o comprovante, uma vaga deve ser preenchida.
slotsAvailable--

Atente-se aos campos e dados pedidos no esquema do banco de dados em majorEvents/UID/subscriptions/UID

Coleta de presenças on-line

Implementar um sistema para coletar as presenças de eventos on-line através da inserção do código de confirmação.
O código de confirmação é gerado na criação do evento e armazenado no BD.

Apesar do código poder ser repassado entre os alunos por mensagem, por exemplo, não é necessário implementar nenhuma segurança, como códigos únicos ou temporários.

Redirecionando o usuário

Considere a seguinte estrutura:

"pending": {
    "attendance": ["UID1", "UID2"]
}

Quando o usuário faz login ou abre o aplicativo já logado, o seguinte código é executado:

if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
this.CompareUserdataVersion(this.userData);

  • Se a função CompareUserdataVersion() não redirecionar o usuário para a página de registro (faça a verificação. Será que usa promises?), execute uma função para verificar as pendências de presença:

  • Para cada elemento do array "attendance", verifique a partir do UID se data do início da coleta de presença < agora e que data do fim da coleta de presença === undefined/null.

  • Se um UID tiver essas condições, redirecione o usuário para a página de coleta de presença.

  • Se você encontrar uma data final definida, remova o UID do array. A coleta de presença já encerrou.

  • Pode ser que dois eventos estejam com coleta de presença abertas ao mesmo tempo. Se conseguir, trate esta situação.

Página para inserção

  • Ao abrir a página, o campo do 1º caractere deve ser selecionado e o teclado do celular deve abrir sozinho.

  • Após digitar um caractere, o focus deve avançar para o próximo campo, para que o próximo caractere possa ser digitado.

  • Ao digitar o último caractere, o teclado NÃO deve ser fechado. Se todos os caracteres foram digitados deve ocorrer a validação do código inserido.

    • Se for válido, fechar teclado, apresentar swal de confirmação e fechar a página, tudo automaticamente
    • Se for inválido, alterar a cor das linhas, caracteres e "insira o código" para vermelho. Quando o usuário alterar um caractere, realize a verificação novamente.

Escrevendo no BD

Note: Regra no BD
Se o evento tem coleta de presença on-line, permita que o usuário escreva o campo time no seu próprio documento na lista de presenças.

Após a validação do código, verifique se o usuário está inscrito e é pagante.

  • Se sim, escreva o campo time com a hora atual em:
    events/UIDevento/attendance/UIDusuário

  • Além disso, remova o UID do evento do array attendance, no campo pending em:
    users/UIDusuario

"pending": {
    "attendance": ["UID1", "UID2"]
}
  • Se não, apresente uma mensagem de erro que exige que o botão "ok" seja pressionado e redirecione o usuário ao menu.

Não há motivação para coletar a presença on-line de quem não está inscrito

Extra

Pode ser feito após a SECOMPP

  • Coletar a presença através da leitura de um QR Code

Image

event:UIDEvento:código

Redireciona para a página, preenche os campos sozinho e valida a presença

Implementar novos cargos

Atualmente, existe apenas a custom claim "role: 1000".
Para a expansão do uso do app, é necessário que haja diferentes permissões, que podem ser adotadas num sistema hierárquico de 4 números. Exemplo:

Admin - 1000
CAS - 2000:
    CACiC - 2120:
        Presidente - 2121
        Diretor - 2122
EJs - 3000
Professores - 4000
Estudantes - 5000:
    Computação - 5120
Público externo - 6000

Com este tipo de hierarquia, é possível controlar o acesso às diferentes partes do app.

Coleta de presenças da comunidade externa

Atualmente, só é possível coletar a presença de alunos da Unesp cadastrados no app.
Deve haver uma maneira para coletar a presença de pessoas externas, para eventos como a SECOMPP, por exemplo.

Porém, antes de implementar esta funcionalidade, deve-se avaliar se ela é necessária, ou seja, se haverá um número de pessoas externas considerável nos eventos para justificar a sua implementação.

O preenchimento manual dos dados é uma opção. Neste caso, os dados podem ser armazenados no firestore e vinculados ao CPF (ideal, por ser imutável) ou número de celular (menos invasivo) da pessoa, para preenchimento automático nas próximas presenças.

Outra opção, que pode ser utilizada em conjunto com a inscrição de pessoas externas em eventos, é habilitar a criação de contas no app para pessoas sem o e-mail institucional da Unesp.

Página para adicionar grandes eventos

"Grandes eventos" são um grupo que abrigam eventos menores.
Por exemplo:
SECOMPP - grande evento
Minicursos da SECOMPP - eventos menores

Grandes eventos serão apresentados em um menu dedicado. É possível selecionar um grande evento para inscrever-se em eventos menores (veja #51 e #49). Somente quando o pagamento for confirmado, a inscrição será realizada no grande evento e nos eventos menores.

Esta página possuirá muitos seletores de data. Implementar de uma maneira em que não haja vários seletores de data hard coded, um para cada campo. Descartado

As seguintes informações deverão ser apresentadas na página de criação do evento e gravadas no banco de dados para a adição de um grande evento:
Informações do evento

  • Curso
  • Nome do evento
  • Descrição do evento

Data do evento

  • Evento dura mais que um dia? Sim/Não
  • Data do início do evento
  • Data do fim do evento (caso a resposta seja "sim")

Inscrições

  • Data do início das inscrições
  • Data do fim das inscrições
  • Máximo de minicursos que dá para se inscrever
  • Máximo de palestras que dá para se inscrever

Preço

  • O evento é gratuito?
  • Diferenciar preço por tipo de inscrição?
    Sim:
  • Aluno da Unesp
  • Aluno de outras IES
  • Professores e profissionais
    Não:
  • Preço único

Informações de pagamento
Pagável por transferência bancária?
Sim:

  • Nome completo do beneficiário
  • CPF ou CNPJ
  • Instituição bancária
  • Agência (sem dígito)
  • Conta (com dígito)
  • Chave Pix (opcional)
  • Informações adicionais (opcional)
    Não:
    Campo de texto com informações do pagamento

Botão (opcional)

  • Texto (opcional) - Texto padrão: "Saiba mais"
  • Link

Outras informações (opcional)

  • Evento aberto ao público?

Armazenar também:

  • Nome do criador do evento
  • Data de criação do evento

Itens não marcados com (opcional) são obrigatórios

Esquema do BD:
https://docs.google.com/spreadsheets/d/1U_rhTCGBUj_N_EYJeuew-mIDUFVpK46HTWQrlGyGNS8

Documentação relevante:
Firebase - Cloud Firestore
AngularFire - Firestore Docs

Leitura de códigos Aztec

O Aztec pode ser lido de distâncias maiores que o QR Code.

Caso o usuário não possa utilizar o celular, o seu código de usuário pode ser impresso, para agilizar a coleta de presença.
Se comparado com o QR Code, códigos Aztec são melhores para impressão em papel comum.
O QR Code possui 3 finder patterns nas pontas. Caso o ticket seja rasgado em uma destas pontas, o código é inutilizado.

Os finder patterns do Aztec estão no centro

Arrumar ícone PWA

O mask que acontece no Android está cortando as bordas do ícone.
O tamanho do ícone precisa ser reduzido.

SMS cai no spam

De acordo com este comentário no stackoverflow, o %APP_NAME% do SMS é sempre o URL do site, então, por conter um link, pode ser que a mensagem caia no spam do celular.

Celular, vínculo e RA não são escritos no BD

Algumas inscrições vem normais.
Algumas inscrições vem apenas sem o celular.
Algumas inscrições vem sem vínculo, sem RA e sem celular.

Algumas inscrições estavam vindo sem CPF, mas normalizou.

Obter uid através do e-mail ou celular

Uma função que retorna o uid do usuário quando o administrador insere o e-mail ou celular da pessoa.

Já existe uma opção no console do Firebase para consultar uid pelo e-mail do cadastro

Página para adicionar eventos

Caso o evento pertença a um grande evento, deve-se adicionar o UID do evento ao array "events" armazenado no documento do grande evento.

As seguintes informações deverão ser apresentadas na página de criação do evento e gravadas no banco de dados para a adição de um evento:
Informações do evento

  • Curso
  • Nome do evento
  • Descrição curta do evento
  • Descrição do evento
  • Emoji do evento
  • Data do evento
  • Horário de término (opcional)
  • Dropdown Pertence ao grande evento: opção "Nenhum" (padrão); listar os futuros grandes eventos embaixo
    • Dropdown Tipo de evento: Evento é minicurso, palestra ou nenhum?

Localização (opcional)

  •  Dropdown com predefinições de lugares
  •  Endereço ou descrição
  •  Latitude
  •  Longitude

Se ou a latitude ou a longitude for preenchida, a outra se torna obrigatória

Botão (opcional)

  • Texto (opcional) - Texto padrão: "Acompanhe o evento"
  • Link

Outras informações (opcional)

  • Código do YouTube
  • Coletar presenças para este evento? (padrão não)
    • Emite certificado de participação? (padrão não)
    • Coleta dupla de presença? (padrão não)
  • Evento aberto ao público (padrão sim)

Armazenar também:

  • UID do criador do evento - Na página, exibir o nome armazenado no localstorage
  • Data de criação do evento

Esquema do BD:
https://docs.google.com/spreadsheets/d/1U_rhTCGBUj_N_EYJeuew-mIDUFVpK46HTWQrlGyGNS8

Documentação relevante:
Firebase - Cloud Firestore
AngularFire - Firestore Docs

Listar eventos inscritos e presenças do usuário

Checklist

Página principal
Cards

  • Aguardando envio
  • Envio realizado
  • Erro no pagamento
  • Não há vagas
  • Eventos passados
    • Sem emissão de certificado
    • Com emissão de certificado

Página principal

A página deve permitir que o usuário visualize todos os eventos em que ele esteve presente ou que ele pagou.

A página deve exibir ambos majorEvents e events. Exibir apenas os events que não fazem parte de um majorEvent.

Se possível, considerar as seguintes situações:

Situação Exibir card do evento?
Usuário se inscreveu e pagou Sim
Usuário se inscreveu, mas não pagou e o evento finalizou Sim
Usuário se inscreveu, mas o evento não coleta presença Não
Usuário se inscreveu, evento coleta presença, mas não emite certificado Sim, sem botão de certificado
Demais situações Sim

Dentre as informações apresentadas em #46, considere que:

  • Não é possível reenviar ou exibir o comprovante de pagamento.
  • A data limite para o pagamento é a data fim das inscrições, após isso, não exibir mais o botão de inscrição

Por conta da complexidade em exibir os dados, você tem liberdade para solicitar alterações na estrutura do banco de dados.

Considerando que o Firebase cobra por leitura de documento, limite a exibição de eventos a um número pequeno, NÃO impedindo que o usuário possa ver seus eventos mais antigos

Documentação relevante:

Especificações

image Botão no menu principal
image Aguardando usuário realizar o pagamento e o envio do comprovante
Apesar de haver dois botões diferentes, eles redirecionam para a mesma página, para evitar ambiguidades
Se você conseguir, exiba os dois botões com o mesmo tamanho
image Comprovante já enviado, aguardando admin validar
ou
Inscrição confirmada
Não exibir nenhum botão, apenas a mensagem
image Houve algum erro no pagamento
Exibir a mensagem de erro, o botão "REenviar comprovante" e os demais textos do card em color="danger"
O objetivo da cor é deixar visível que há algum problema com a inscrição
image Não há mais vaga numa das atividades selecionadas
image Eventos passados
Exibir os botões em color="secondary" para diferenciar de eventos atuais
Faça apenas os botões, não as páginas

Validador de certificados

Layout do certificado

Nome Descrição
date Data no formato "13 de dezembro de 2022"
participation_type Campo personalizado
name Nome completo do usuário (fullName, não displayName)
event_type Campo personalizado
event_name Nome do evento
url URL para verificação do certificado
qrcode O mesmo valor de URL
name_small Mesmo valor que o campo "name"
document String com o documento do usuário, ex: "CPF: 000.000.000-00"
event_name_small Mesmo valor que o campo "event_name"
content Descrição das atividades realizadas

Screenshot 2022-12-15 at 16 09 57

Especificações

Considere a rota como
https://fct-pp.web.app/certificado/validar/:código

Se o código não for preenchido na URL, direcionar para a página de "Insira o código"

Se o código estiver preenchido na URL, ir direto para a página de certificado válido.

Se o certificado for inválido, redirecionar para a página de "insira o código", preenchendo o input com o ID e exibindo a mensagem de certificado não encontrado.

image

image

Página para gerenciar grandes eventos

A página lista os Grandes Eventos mês a mês.
Por exemplo:
Se o usuário selecionar o mês de setembro, a página deve exibir os grandes eventos que iniciam entre 01/09/2022 00:00 e 30/09/2022 23:59:59

A data padrão (já selecionada quando a página carrega) deve ser o mês atual.
Para obter o dia de hoje, use new Date().

Nesta página, deve haver um indicador de carregamento e uma mensagem caso nenhum evento seja encontrado no mês consultado.

Para evitar consultas desnecessárias em datas distantes (eventos no ano de 2057, por exemplo), limite o seletor para no máximo 1 ano da data de "hoje".
Inicie o seletor de datas passadas em 03/2022.

Documentação relevante:

Referências no código já implementado:

A página deve conter 2 botões:

  • Gerenciar inscritos (#57)
  • Validar comprovantes (#47)

Essas páginas não pertencem a esta issue, apenas os botões devem ser feitos

Emissão de certificados - Cloud function

Nesta tarefa, você estará gerando os dados que serão armazenados no banco de dados. Você não gerará PDFs.

• Por que não gerar certificados sob demanda, sem duplicar os dados?
Para possibilitar a validação on-line do certificado e para evitar que alterações no nome do usuário e documento reflitam nos dados apresentados no certificado.

Layout do certificado

Nome Descrição
date Data no formato "13 de dezembro de 2022"
participation_type Campo personalizado
name Nome completo do usuário (fullName, não displayName)
event_type Campo personalizado
event_name Nome do evento
url URL para verificação do certificado
qrcode O mesmo valor de URL
name_small Mesmo valor que o campo "name"
document String com o documento do usuário, ex: "CPF: 000.000.000-00"
event_name_small Mesmo valor que o campo "event_name"
content Descrição das atividades realizadas

Screenshot 2022-12-15 at 16 09 57

Especificações

Orientações gerais

Gere apenas 1 certificado por MajorEvent ou por EventGroup.
Ex: Se o MajorEvent/EventGroup possui 3 eventos, gere 1 unidade de certificado e só.

Faça uma função generateCertificate que recebe um objeto data e retorna um Object com sucessful: boolean

interface data {
	eventType: "event" | "eventGroup" | "majorEvent";
	eventID: string;
	certificateData: CertificateIssuingData
}

Emissão dos certificados

Os certificados devem ser gerados no ambiente de Cloud Functions, para evitar problemas com permissões e eliminar a possibilidade da emissão ser interrompida por problemas de internet.

Note
O código deve ser eficiente, pois o tempo de execução e RAM são pagos

Retomada de uma emissão que falhou

  • Pronto 👆

Durante a geração do certificado de múltiplas pessoas, armazenar no BD:

  • O ID do usuário que iniciou a emissão
  • O ID do último usuário que teve o certificado gerado com sucesso
  • A quantidade de certificados já gerados
  • As informações do formulário

Depois de uma emissão bem-sucedida:

  • Limpar todos os dados temporários no BD

Caso a emissão tenha falhado:

  • Exibir erro para o admin
  • Permitir a retomada emissão de onde ela parou

Campo content

Major events

Palestras:
• 22/12/2022 10:00 - Palestra de AI - 10 horas
• 22/12/2022 10:01 - Palestra de BD - 10 horas
Total: 20 horas - 2 palestras

Minicursos:
• 22/12/2022 10:00 - Conhecendo o Git - 10 horas
• 22/12/2022 10:01 - Conhecendo o Firebase - 5 horas
Total: 15 horas - 2 minicursos

Grupo de eventos

Minicursos:
• 22/12/2022 10:00 - Conhecendo o Git - Parte 1 - 10 horas
• 22/12/2022 10:01 - Conhecendo o Git - Parte 2 - 10 horas
Total: 20 horas - 2 minicursos

Coletar presença apenas de inscritos pagantes

  • Ao ler o QR Code ou inserir manualmente a presença, avalie se o evento é pago.

  • Se o evento não for pago, registre todas as leituras na coleção "attendace"

  • Se o evento for pago, avalie se o status do pagamento de usuário é payment.status == 2 (pago e validado).

    • Se for, registre a leitura na coleção "attendace"
    • Se não for, registre a leitura na coleção "non-paying-attendance"

Evite verificar se o evento é pago ou não em cada uma das leituras de presença, faça apenas uma verificação

Download dos certificados em PDF

Especificações

Página de "minhas inscrições"

  • Não mostrar botão de "listar certificados", apenas o "mais detalhes"

Página de "mais detalhes"

  • Fazer uma página de "mais detalhes" para os eventos normais, com o mesmo layout da página do evento no calendário
  • Ocultar o botão de "Listar certificados" caso o usuário não possua nenhum certificado emitido para este evento
  • Adicione um "√ presente" embaixo do horário nos eventos em que o usuário esteve presente
  • Adicione um "√ presente sem pagamento" embaixo do horário nos eventos em que o usuário esteve presente sem pagar

Modal de download

  • Obter as informações do banco de dados e gerar o certificado para download
  • Obtenha o template do certificado diretamente do repositório, utilizando o jsDelivr.
  • Quando o usuário clicar no botão de download, desabilitar o botão e trocar o ícone para um spinner.
  • Quando o download iniciar, habilite o botão e troque o ícone para um checkmark.

Interface de download em Major Events

Screenshot 2022-12-15 at 15 29 40

Inscrição em grandes eventos

  • O usuário deve poder se inscrever em minicursos específicos e, depois, estar liberado para efetuar o pagamento.
    Não é obrigatório selecionar todos os minicursos.

  • Sugere-se que o sistema verifique se há choque de horário entre os minicursos, impedindo a inscrição caso exista.
    Caso a implementação seja difícil, não é necessário.

  • Deve-se verificar, obrigatoriamente, a existência de vagas no curso ou palestra. Esgotando-se o número de vagas, a checkbox é desabilitada.

O id do evento será passado pela URL:
https://fct-pp.web.app/eventos/inscrever/:id
Referência: Rota da página de um evento

Maneira correta de obter o id a partir da URL: https://stackoverflow.com/questions/52364998/get-data-from-url-in-angular-5

Para elaborar o seletor do tipo de inscrição e para gravar no BD, conforme https://github.com/cacic-fct/fct-app/blob/ffbea450daaacb2f3d1189a89691bdb7ef1efbfb/src/app/shared/services/enrollment-types.service.ts, considere:

Código Descrição
0 Aluno da Unesp
1 Aluno de outras IES
2 Professores e profissionais

Considere o campo slotsAvailable para obter o número de vagas restantes
Considere o campo numberOfSubscriptions para obter a posição na fila. Lembre-se de adicionar 1 ao número - se há 0 inscrições, a posição na fila é 1.

Quando a inscrição for finalizada, adicione 1 ao valor do campo numberOfSubscriptions utilizando Cloud Firestore triggers, mais especificamente Trigger a function when a new document is created. Isso é necessário, já que o usuário não pode ter permissão direta para atualizar este valor.
Pode ser que você utilize Cloud Functions e o Firebase Admin SDK.

Para configurar o emulador de Cloud Functions:

cd functions
npm i
npm run build

Uma vaga só é ocupada quando o pagamento é validado, para evitar que várias pessoas se inscrevam e ocupem as vagas sem pagar.

Considere a possibilidade de não haver mais vagas disponíveis quando o pagamento for validado.
Deve ser possível que o usuário edite a sua inscrição caso sua inscrição tenha o status "4 - erro, vagas insuficientes". (Veja como aparecerá na lista de inscrições: #42)

image image
image Emoji do evento
image Use este estilo para a barra da data

Para exibir os dados do evento, reaproveite o código da listagem.


Esquema do BD:
https://docs.google.com/spreadsheets/d/1U_rhTCGBUj_N_EYJeuew-mIDUFVpK46HTWQrlGyGNS8/



Votação preferencial para inscrição em eventos

https://pt.wikipedia.org/wiki/Voto_preferencial

Na SECOMPP22 não houve vagas suficientes em todos os minicursos para todos os inscritos no evento.
Com o sistema de inscrição atual, quando não havia vagas, era necessário retornar a inscrição para o usuário e pedir para que ele selecionasse um evento no qual haveria vagas livres.
Além do usuário voltar para o final da fila de espera, os administradores tiveram que esperar que os usuários editassem a inscrição, o que poderia demorar.

O sistema de inscrição por votação preferencial também elimina a necessidade de recusar a inscrição devido a choque de horário entre alguns dos eventos selecionados.

Pode-se utilizar o ion-reorder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.