gbope commited on
Commit
c0ae6cd
·
verified ·
1 Parent(s): 9829926

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -297
app.py CHANGED
@@ -1,326 +1,92 @@
1
  import gradio as gr
2
  import re
3
- import os
4
-
5
- # Verifica se estamos no Hugging Face Spaces
6
- ON_HUGGINGFACE = "SPACE_ID" in os.environ
7
-
8
- def obter_documentos_padrao_2010_mais():
9
- return [
10
- "Certidão de Nascimento (Não pode ser só o RG)",
11
- "Documento com Foto (RG/CNH/OUTROS - se houver)",
12
- "CPF (se não tiver em outro documento)",
13
- "Foto Corporal Completa para Verificação de Saúde (explicação abaixo)",
14
- "Email e celular do responsável"
15
- ]
16
-
17
- def obter_documentos_padrao_2009_menos():
18
- return [
19
- "Documento com Foto (RG/CNH/OUTROS)",
20
- "CPF (se não tiver no documento com foto)",
21
- "Foto com Documento ao lado do rosto",
22
- "Email e celular"
23
- ]
24
-
25
- def obter_documentos_carencia():
26
- return [
27
- "3 últimos boletos pagos e seus comprovantes",
28
- "Carteirinha",
29
- "Carta de permanência (solicitar à administradora do plano, geralmente por ligação)"
30
- ]
31
-
32
- def obter_documentos_titular(categoria, modalidade, documentos_padrao):
33
- documentos = documentos_padrao.copy()
34
- documentos.append("Comprovante de Residência (no nome do titular ou dos pais)")
35
-
36
- if categoria == "CNPJ":
37
- documentos.append("DA EMPRESA:")
38
- if modalidade == "MEI":
39
- documentos.extend(["CNPJ", "CCMEI"])
40
- elif modalidade == "OUTROS":
41
- documentos.extend(["CNPJ", "Contrato Social e suas alterações"])
42
-
43
- elif categoria == "ADESAO":
44
- documentos_map = {
45
- "ENTIDADE ABERTA": None,
46
- "ESTUDANTE": "Declaração Escolar",
47
- "TRABALHADOR": "Contracheque",
48
- "PROFISSIONAL LIBERAL": "Documento de Registro no Conselho na validade + Diploma",
49
- "APOSENTADO": "Comprovante de Pensão"
50
- }
51
- doc_extra = documentos_map.get(modalidade)
52
- if doc_extra:
53
- documentos.append(doc_extra)
54
-
55
- return documentos
56
-
57
- def simplificar_dependente(nome):
58
- simplificacoes = {
59
- "Cônjuge ou companheiro(a)": "Cônjuge",
60
- "Filhos(as) solteiros naturais, tutelados, enteados e adotivos": "Filhos",
61
- "Filhos(as) inválidos declarados no imposto de renda do titular": "Filho inválido",
62
- "Pai e mãe": "Pais",
63
- "Padrasto e madrasta": "Padrastos",
64
- "Irmãos(ãs) consanguíneos ou adotivos": "Irmãos",
65
- "Netos": "Netos",
66
- "Sobrinhos": "Sobrinhos",
67
- "Primos": "Primos",
68
- "Tios": "Tios",
69
- "Cunhados(as)": "Cunhados",
70
- "Sogro(a)": "Sogro(a)",
71
- "Genros e noras": "Genros/Noras",
72
- "Avô e avó": "Avós"
73
- }
74
- return simplificacoes.get(nome, nome)
75
-
76
- def formatar_documentos(nome, documentos):
77
- resultado = f"<h3>Documentos necessários para {nome}:</h3><ul>"
78
- for doc in documentos:
79
- if doc == "DA EMPRESA:":
80
- resultado += f"</ul><h4>{doc}</h4><ul>"
81
- else:
82
- resultado += f"<li>{doc}</li>"
83
- resultado += "</ul>"
84
- return resultado
85
-
86
- def obter_documentos_dependente(dependente, nascido_2010):
87
- documentos = obter_documentos_padrao_2010_mais() if nascido_2010 else obter_documentos_padrao_2009_menos()
88
-
89
- if dependente == "Cônjuge ou companheiro(a)":
90
- documentos.append("Certidão de casamento ou declaração de união estável (lavrada em cartório).")
91
- elif "inválido" in dependente:
92
- documentos.append("Declaração de imposto de renda do titular comprovando a condição.")
93
- elif dependente in ["Netos", "Sobrinhos", "Primos", "Tios"]:
94
- documentos.append("Documento com foto (RG/CNH/outros) do pai/mãe.")
95
- elif dependente in ["Cunhados(as)", "Genros e noras"]:
96
- documentos.append("Certidão de casamento.")
97
- elif dependente == "Sogro(a)":
98
- documentos.append("Certidão de casamento do titular")
99
-
100
- return documentos
101
-
102
- def processar_documentos(titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info):
103
- resultado = ""
104
- lista_completa = []
105
- docs_carencia = obter_documentos_carencia()
106
-
107
- # Documentos do titular
108
- documentos_padrao_titular = obter_documentos_padrao_2010_mais() if titular_nascido_2010 else obter_documentos_padrao_2009_menos()
109
- documentos_titular = obter_documentos_titular(categoria, modalidade, documentos_padrao_titular)
110
-
111
- if titular_carencia:
112
- documentos_titular.extend(docs_carencia)
113
-
114
- lista_completa.append(("TITULAR", documentos_titular))
115
-
116
- if dependentes_info:
117
- for dep_info in dependentes_info:
118
- dep_nascido_2010, dep_tipo, dep_carencia = dep_info
119
- nome_simples = simplificar_dependente(dep_tipo)
120
- docs_dep = obter_documentos_dependente(dep_tipo, dep_nascido_2010)
121
-
122
- if dep_carencia:
123
- docs_dep.extend(docs_carencia)
124
-
125
- lista_completa.append((f"Dependente: {nome_simples}", docs_dep))
126
-
127
- for nome, documentos in lista_completa:
128
- resultado += formatar_documentos(nome, documentos)
129
-
130
- return resultado
131
-
132
- def atualizar_lista_inclusos(titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info):
133
- lista_inclusos = []
134
-
135
- # Adiciona titular
136
- tipo_titular = "Titular (2010+)" if titular_nascido_2010 else "Titular (2009-)"
137
- if titular_carencia:
138
- tipo_titular += " + carência"
139
- lista_inclusos.append([tipo_titular, categoria, modalidade if modalidade else "PF"])
140
-
141
- # Adiciona dependentes
142
- if dependentes_info:
143
- for dep_info in dependentes_info:
144
- dep_nascido_2010, dep_tipo, dep_carencia = dep_info
145
- tipo_dep = f"Dep. {simplificar_dependente(dep_tipo)} (2010+)" if dep_nascido_2010 else f"Dep. {simplificar_dependente(dep_tipo)} (2009-)"
146
- if dep_carencia:
147
- tipo_dep += " + carência"
148
- lista_inclusos.append([tipo_dep, "Dependente", dep_tipo])
149
-
150
- return lista_inclusos
151
 
152
  def limpar_texto_para_copiar(texto):
 
153
  texto_limpo = re.sub('<[^<]+?>', '', texto)
154
  texto_limpo = texto_limpo.replace('</ul>', '\n').replace('</li>', '\n')
155
  texto_limpo = re.sub('\n+', '\n', texto_limpo).strip()
156
  return texto_limpo
157
 
158
- def copiar_para_area_transferencia(texto):
159
- try:
160
- if not texto:
161
- return "❌ Nada para copiar - gere a lista primeiro"
162
-
163
- texto_limpo = limpar_texto_para_copiar(texto)
164
-
165
- if ON_HUGGINGFACE:
166
- return {
167
- "mensagem": "✅ Clique no texto abaixo e pressione Ctrl+C para copiar",
168
- "texto": texto_limpo
169
- }
170
- else:
171
- import pyperclip
172
- pyperclip.copy(texto_limpo)
173
- return {
174
- "mensagem": "✅ Copiado para área de transferência!",
175
- "texto": ""
176
- }
177
- except Exception as e:
178
- return {
179
- "mensagem": f"❌ Erro: {str(e)}",
180
- "texto": ""
181
  }
182
-
183
- def atualizar_modalidades(categoria):
184
- if categoria == "CNPJ":
185
- return gr.Dropdown(choices=["MEI", "OUTROS"], label="Modalidade CNPJ", interactive=True)
186
- elif categoria == "ADESAO":
187
- return gr.Dropdown(
188
- choices=["ENTIDADE ABERTA", "ESTUDANTE", "TRABALHADOR", "PROFISSIONAL LIBERAL", "APOSENTADO"],
189
- label="Modalidade Adesão",
190
- interactive=True
191
- )
192
- else:
193
- return gr.Dropdown(choices=[], label="Modalidade (não aplicável)", interactive=False)
194
-
195
- def criar_interface():
196
- with gr.Blocks(title="Documentos para Plano de Saúde", theme=gr.themes.Soft()) as app:
197
- gr.Markdown("# 📋 Documentos Necessários para Plano de Saúde")
198
- gr.Markdown("Preencha os dados abaixo para obter a lista de documentos necessários.")
199
-
200
- with gr.Row():
201
- with gr.Column():
202
- # Seção do Titular
203
- with gr.Group():
204
- gr.Markdown("### Titular")
205
- categoria = gr.Radio(
206
- choices=["PF", "CNPJ", "ADESAO"],
207
- label="Categoria do Titular",
208
- value="PF"
209
- )
210
- modalidade = gr.Dropdown(
211
- choices=[],
212
- label="Modalidade (se aplicável)",
213
- interactive=False
214
- )
215
- with gr.Row():
216
- titular_nascido_2010 = gr.Checkbox(label="Nasceu em 2010 ou depois?")
217
- titular_carencia = gr.Checkbox(label="Fará compra de carência?")
218
-
219
- # Seção de Dependentes
220
- with gr.Accordion("Adicionar Dependentes", open=True) as accordion_deps:
221
- with gr.Group():
222
- gr.Markdown("### Novo Dependente")
223
- dep_tipo = gr.Dropdown(
224
- choices=[
225
- "Cônjuge ou companheiro(a)",
226
- "Filhos(as) solteiros naturais, tutelados, enteados e adotivos",
227
- "Filhos(as) inválidos declarados no imposto de renda do titular",
228
- "Pai e mãe",
229
- "Padrasto e madrasta",
230
- "Irmãos(ãs) consanguíneos ou adotivos",
231
- "Netos",
232
- "Sobrinhos",
233
- "Primos",
234
- "Tios",
235
- "Cunhados(as)",
236
- "Sogro(a)",
237
- "Genros e noras",
238
- "Avô e avó"
239
- ],
240
- label="Tipo de Dependente"
241
- )
242
- with gr.Row():
243
- dep_nascido_2010 = gr.Checkbox(label="Nasceu em 2010 ou depois?")
244
- dep_carencia = gr.Checkbox(label="Fará compra de carência?")
245
- btn_adicionar_dep = gr.Button("➕ Adicionar Dependente", variant="primary")
246
-
247
- lista_inclusos = gr.Dataframe(
248
- headers=["Inclusos nessa cotação", "Tipo", "Detalhes"],
249
- datatype=["str", "str", "str"],
250
- interactive=False,
251
- label="Inclusos nessa cotação",
252
- value=[["Titular (2009-)", "PF", ""]]
253
- )
254
- dependentes_info = gr.State([])
255
-
256
- btn_submit = gr.Button("🔍 Gerar Lista de Documentos", variant="primary")
257
-
258
- with gr.Column():
259
- output = gr.HTML(label="Documentos Necessários")
260
- btn_copiar = gr.Button("📋 Copiar Lista")
261
- status_copia = gr.Textbox(label="Status", interactive=False, visible=False)
262
- texto_para_copiar = gr.Textbox(visible=False)
263
 
264
- # Atualiza modalidades quando categoria muda
265
- categoria.change(
266
- atualizar_modalidades,
267
- inputs=categoria,
268
- outputs=modalidade
 
 
 
 
269
  )
270
 
271
- # Atualiza lista de inclusos em tempo real
272
- inputs_lista = [titular_nascido_2010, categoria, modalidade, titular_carencia, dependentes_info]
273
- for input_component in inputs_lista:
274
- input_component.change(
275
- atualizar_lista_inclusos,
276
- inputs=inputs_lista,
277
- outputs=lista_inclusos
278
- )
279
 
280
- # Adiciona dependentes à lista
281
- btn_adicionar_dep.click(
282
- lambda dep_info, dep_nasc, dep_tipo, dep_carencia: (dep_info + [(dep_nasc, dep_tipo, dep_carencia)]),
283
- inputs=[dependentes_info, dep_nascido_2010, dep_tipo, dep_carencia],
284
- outputs=dependentes_info
285
- ).then(
286
- atualizar_lista_inclusos,
287
- inputs=inputs_lista,
288
- outputs=lista_inclusos
289
- )
290
 
291
- # Processa o formulário
292
  btn_submit.click(
293
  processar_documentos,
294
- inputs=[
295
- titular_nascido_2010,
296
- categoria,
297
- modalidade,
298
- titular_carencia,
299
- dependentes_info
300
- ],
301
  outputs=output
302
  ).then(
303
- lambda x: limpar_texto_para_copiar(x),
304
  inputs=output,
305
  outputs=texto_para_copiar
306
  )
307
 
308
- # Copia para área de transferência
309
  btn_copiar.click(
310
- copiar_para_area_transferencia,
311
- inputs=output,
312
- outputs=[status_copia, texto_para_copiar],
313
  js="""
314
- (data) => {
315
- if (data.texto) {
 
 
 
316
  const textarea = document.createElement('textarea');
317
- textarea.value = data.texto;
318
  document.body.appendChild(textarea);
319
  textarea.select();
320
  document.execCommand('copy');
321
  document.body.removeChild(textarea);
 
322
  }
323
- return [data.mensagem, data.texto];
324
  }
325
  """
326
  ).then(
@@ -329,8 +95,4 @@ def criar_interface():
329
  status_copia
330
  )
331
 
332
- return app
333
-
334
- # Criar e lançar a interface
335
- interface = criar_interface()
336
- interface.launch()
 
1
  import gradio as gr
2
  import re
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  def limpar_texto_para_copiar(texto):
5
+ # Remove tags HTML e formata para texto puro
6
  texto_limpo = re.sub('<[^<]+?>', '', texto)
7
  texto_limpo = texto_limpo.replace('</ul>', '\n').replace('</li>', '\n')
8
  texto_limpo = re.sub('\n+', '\n', texto_limpo).strip()
9
  return texto_limpo
10
 
11
+ def criar_botao_copiar():
12
+ # JavaScript que será injetado na interface
13
+ js = """
14
+ async function copiarTexto() {
15
+ const texto = document.querySelector("#texto-para-copiar textarea").value;
16
+ try {
17
+ await navigator.clipboard.writeText(texto);
18
+ return "✅ Copiado para área de transferência!";
19
+ } catch (err) {
20
+ // Fallback para o método antigo se o novo não funcionar
21
+ const textarea = document.createElement('textarea');
22
+ textarea.value = texto;
23
+ document.body.appendChild(textarea);
24
+ textarea.select();
25
+ document.execCommand('copy');
26
+ document.body.removeChild(textarea);
27
+ return "✅ Copiado (método alternativo)!";
 
 
 
 
 
 
28
  }
29
+ }
30
+ """
31
+
32
+ with gr.Blocks() as demo:
33
+ texto_para_copiar = gr.Textbox(visible=False)
34
+ btn_copiar = gr.Button("📋 Copiar Lista")
35
+ status_copia = gr.Textbox(label="Status", interactive=False, visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ btn_copiar.click(
38
+ fn=lambda x: x, # Função vazia, o trabalho é feito no JavaScript
39
+ inputs=texto_para_copiar,
40
+ outputs=status_copia,
41
+ js=js + "async () => { return await copiarTexto(); }"
42
+ ).then(
43
+ lambda: gr.update(visible=True),
44
+ None,
45
+ status_copia
46
  )
47
 
48
+ return demo
49
+
50
+ # Adicione esta função à sua interface principal
51
+ def criar_interface_completa():
52
+ with gr.Blocks() as app:
53
+ # ... (todo o resto do seu código existente)
 
 
54
 
55
+ # Substitua a parte do botão de copiar por:
56
+ texto_para_copiar = gr.Textbox(visible=False)
57
+ btn_copiar = gr.Button("📋 Copiar Lista")
58
+ status_copia = gr.Textbox(label="Status", interactive=False, visible=False)
 
 
 
 
 
 
59
 
60
+ # Quando gerar a lista de documentos:
61
  btn_submit.click(
62
  processar_documentos,
63
+ inputs=[...],
 
 
 
 
 
 
64
  outputs=output
65
  ).then(
66
+ limpar_texto_para_copiar,
67
  inputs=output,
68
  outputs=texto_para_copiar
69
  )
70
 
71
+ # Configuração do botão de copiar
72
  btn_copiar.click(
73
+ fn=lambda x: x,
74
+ inputs=texto_para_copiar,
75
+ outputs=status_copia,
76
  js="""
77
+ async (texto) => {
78
+ try {
79
+ await navigator.clipboard.writeText(texto);
80
+ return "✅ Copiado para área de transferência!";
81
+ } catch (err) {
82
  const textarea = document.createElement('textarea');
83
+ textarea.value = texto;
84
  document.body.appendChild(textarea);
85
  textarea.select();
86
  document.execCommand('copy');
87
  document.body.removeChild(textarea);
88
+ return "✅ Copiado (use Ctrl+C se não colar automaticamente)";
89
  }
 
90
  }
91
  """
92
  ).then(
 
95
  status_copia
96
  )
97
 
98
+ return app