devorah-ai-2016 commited on
Commit
afa132b
·
verified ·
1 Parent(s): eb9fbdc

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -450
app.py DELETED
@@ -1,450 +0,0 @@
1
- import streamlit as st
2
- import sqlite3
3
- import pandas as pd
4
- from datetime import datetime
5
- import os
6
-
7
- DB_DIR = "data"
8
- DB_PATH = os.path.join(DB_DIR, "clients.db")
9
-
10
- os.makedirs(DB_DIR, exist_ok=True)
11
-
12
- st.set_page_config(
13
- page_title="Client Center",
14
- page_icon="👥",
15
- layout="wide"
16
- )
17
-
18
- # -----------------------------
19
- # DB 연결 및 테이블 생성
20
- # -----------------------------
21
- def get_conn():
22
- return sqlite3.connect(DB_PATH, check_same_thread=False)
23
-
24
- def init_db():
25
- conn = get_conn()
26
- cur = conn.cursor()
27
- cur.execute("""
28
- CREATE TABLE IF NOT EXISTS clients (
29
- id INTEGER PRIMARY KEY AUTOINCREMENT,
30
- name TEXT NOT NULL,
31
- masked_name TEXT,
32
- gender TEXT,
33
- birth_year TEXT,
34
- care_grade TEXT,
35
- institution_type TEXT,
36
- institution_name TEXT,
37
- admission_date TEXT,
38
- main_condition TEXT,
39
- cognitive_status TEXT,
40
- mobility_status TEXT,
41
- diet_status TEXT,
42
- toileting_status TEXT,
43
- guardian_name TEXT,
44
- guardian_phone TEXT,
45
- notes TEXT,
46
- status TEXT DEFAULT '이용중',
47
- created_at TEXT,
48
- updated_at TEXT
49
- )
50
- """)
51
- conn.commit()
52
- conn.close()
53
-
54
- def mask_name(name):
55
- if not name:
56
- return ""
57
- name = name.strip()
58
- if len(name) >= 3:
59
- return name[0] + "○" + name[2:]
60
- elif len(name) == 2:
61
- return name[0] + "○"
62
- return name
63
-
64
- init_db()
65
-
66
- # -----------------------------
67
- # CSS 디자인
68
- # -----------------------------
69
- st.markdown("""
70
- <style>
71
- .main {
72
- background-color: #f8fafc;
73
- }
74
- .block-container {
75
- padding-top: 2rem;
76
- }
77
- .title-box {
78
- background: linear-gradient(135deg, #2E7D32, #66BB6A);
79
- padding: 28px;
80
- border-radius: 18px;
81
- color: white;
82
- text-align: center;
83
- margin-bottom: 25px;
84
- }
85
- .title-box h1 {
86
- margin: 0;
87
- font-size: 34px;
88
- }
89
- .title-box p {
90
- font-size: 17px;
91
- margin-top: 8px;
92
- }
93
- .card {
94
- background: white;
95
- padding: 22px;
96
- border-radius: 16px;
97
- border: 1px solid #e5e7eb;
98
- box-shadow: 0 4px 10px rgba(0,0,0,0.04);
99
- margin-bottom: 16px;
100
- }
101
- .notice {
102
- background: #fff8e1;
103
- padding: 15px;
104
- border-left: 6px solid #f9a825;
105
- border-radius: 10px;
106
- margin-bottom: 20px;
107
- }
108
- </style>
109
- """, unsafe_allow_html=True)
110
-
111
- st.markdown("""
112
- <div class="title-box">
113
- <h1>👥 Client Center</h1>
114
- <p>수급자·입소자 등록 / 검색 / 수정 / 엑셀 업로드 관리센터</p>
115
- </div>
116
- """, unsafe_allow_html=True)
117
-
118
- st.markdown("""
119
- <div class="notice">
120
- <strong>안내:</strong> 생년월일 전체 대신 출생연도 중심으로 입력하고, 이름은 자동으로 홍○동 형식으로 가명 처리됩니다.
121
- </div>
122
- """, unsafe_allow_html=True)
123
-
124
- menu = st.sidebar.radio(
125
- "메뉴 선택",
126
- ["수급자 등록", "수급자 목록", "수급자 검색", "엑셀 업로드", "수정 / 삭제"]
127
- )
128
-
129
- # -----------------------------
130
- # 등록
131
- # -----------------------------
132
- if menu == "수급자 등록":
133
- st.subheader("📝 수급자 직접 등록")
134
-
135
- with st.form("client_form"):
136
- col1, col2, col3 = st.columns(3)
137
-
138
- with col1:
139
- name = st.text_input("수급자 이름")
140
- gender = st.selectbox("성별", ["여", "남", "기타"])
141
- birth_year = st.text_input("출생연도", placeholder="예: 1942")
142
-
143
- with col2:
144
- care_grade = st.selectbox(
145
- "장기요양등급",
146
- ["1등급", "2등급", "3등급", "4등급", "5등급", "인지지원등급", "등급외", "미입력"]
147
- )
148
- institution_type = st.selectbox(
149
- "기관 유형",
150
- ["방문요양", "방문목욕", "방문간호", "주간보호", "요양원", "공동생활가정"]
151
- )
152
- institution_name = st.text_input("기관명")
153
-
154
- with col3:
155
- admission_date = st.date_input("이용 시작일 / 입소일")
156
- status = st.selectbox("상태", ["이용중", "입소중", "퇴소", "중지", "사망"])
157
-
158
- st.markdown("### 건강 및 생활 상태")
159
-
160
- col4, col5 = st.columns(2)
161
-
162
- with col4:
163
- main_condition = st.text_area("주요 질환 / 상태", placeholder="예: 치매, 고혈압, 당뇨, 낙상위험 등")
164
- cognitive_status = st.text_area("인지 상태", placeholder="예: 단기기억 저하, 지남력 저하 등")
165
- mobility_status = st.text_area("이동 상태", placeholder="예: 워커 사용, 부축 필요, 휠체어 사용 등")
166
-
167
- with col5:
168
- diet_status = st.text_area("식사 상태", placeholder="예: 일반식, 죽식, 연하곤란, 식사보조 필요 등")
169
- toileting_status = st.text_area("배변 / 배뇨 상태", placeholder="예: 기저귀 착용, 화장실 유도 필요 등")
170
- notes = st.text_area("특이사항 / 메모")
171
-
172
- st.markdown("### 보호자 정보")
173
-
174
- col6, col7 = st.columns(2)
175
- with col6:
176
- guardian_name = st.text_input("보호자 이름")
177
- with col7:
178
- guardian_phone = st.text_input("보호자 연락처")
179
-
180
- submitted = st.form_submit_button("등록하기")
181
-
182
- if submitted:
183
- if not name:
184
- st.error("수급자 이름은 필수입니다.")
185
- else:
186
- conn = get_conn()
187
- cur = conn.cursor()
188
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
189
-
190
- cur.execute("""
191
- INSERT INTO clients (
192
- name, masked_name, gender, birth_year, care_grade,
193
- institution_type, institution_name, admission_date,
194
- main_condition, cognitive_status, mobility_status,
195
- diet_status, toileting_status, guardian_name,
196
- guardian_phone, notes, status, created_at, updated_at
197
- )
198
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
199
- """, (
200
- name,
201
- mask_name(name),
202
- gender,
203
- birth_year,
204
- care_grade,
205
- institution_type,
206
- institution_name,
207
- str(admission_date),
208
- main_condition,
209
- cognitive_status,
210
- mobility_status,
211
- diet_status,
212
- toileting_status,
213
- guardian_name,
214
- guardian_phone,
215
- notes,
216
- status,
217
- now,
218
- now
219
- ))
220
-
221
- conn.commit()
222
- conn.close()
223
- st.success(f"{mask_name(name)} 수급자가 등록되었습니다.")
224
-
225
- # -----------------------------
226
- # 목록
227
- # -----------------------------
228
- elif menu == "수급자 목록":
229
- st.subheader("📋 수급자 목록")
230
-
231
- conn = get_conn()
232
- df = pd.read_sql_query("SELECT * FROM clients ORDER BY id DESC", conn)
233
- conn.close()
234
-
235
- if df.empty:
236
- st.info("등록된 수급자가 없습니다.")
237
- else:
238
- show_cols = [
239
- "id", "masked_name", "gender", "birth_year", "care_grade",
240
- "institution_type", "institution_name", "status", "admission_date"
241
- ]
242
- st.dataframe(df[show_cols], use_container_width=True)
243
-
244
- # -----------------------------
245
- # 검색
246
- # -----------------------------
247
- elif menu == "수급자 검색":
248
- st.subheader("🔍 수급자 검색")
249
-
250
- keyword = st.text_input("이름, 기관명, 등급, 상태로 검색")
251
-
252
- if keyword:
253
- conn = get_conn()
254
- query = """
255
- SELECT * FROM clients
256
- WHERE name LIKE ?
257
- OR masked_name LIKE ?
258
- OR institution_name LIKE ?
259
- OR care_grade LIKE ?
260
- OR status LIKE ?
261
- ORDER BY id DESC
262
- """
263
- like_keyword = f"%{keyword}%"
264
- df = pd.read_sql_query(
265
- query,
266
- conn,
267
- params=(like_keyword, like_keyword, like_keyword, like_keyword, like_keyword)
268
- )
269
- conn.close()
270
-
271
- if df.empty:
272
- st.warning("검색 결과가 없습니다.")
273
- else:
274
- st.dataframe(df, use_container_width=True)
275
-
276
- # -----------------------------
277
- # 엑셀 업로드
278
- # -----------------------------
279
- elif menu == "엑셀 업로드":
280
- st.subheader("📤 엑셀 업로드")
281
-
282
- st.info("""
283
- 엑셀 권장 컬럼:
284
- 이름, 성별, 출생연도, 장기요양등급, 기관유형, 기관명, 이용시작일, 주요상태, 보호자명, 보호자연락처
285
- """)
286
-
287
- uploaded_file = st.file_uploader("엑셀 파일 업로드", type=["xlsx", "xls"])
288
-
289
- if uploaded_file:
290
- try:
291
- df = pd.read_excel(uploaded_file)
292
- st.write("업로드된 엑셀 미리보기")
293
- st.dataframe(df, use_container_width=True)
294
-
295
- if st.button("DB에 저장하기"):
296
- conn = get_conn()
297
- cur = conn.cursor()
298
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
299
-
300
- for _, row in df.iterrows():
301
- name = str(row.get("이름", "")).strip()
302
- if not name:
303
- continue
304
-
305
- cur.execute("""
306
- INSERT INTO clients (
307
- name, masked_name, gender, birth_year, care_grade,
308
- institution_type, institution_name, admission_date,
309
- main_condition, guardian_name, guardian_phone,
310
- status, created_at, updated_at
311
- )
312
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
313
- """, (
314
- name,
315
- mask_name(name),
316
- str(row.get("성별", "")),
317
- str(row.get("출생연도", "")),
318
- str(row.get("장기요양등급", "")),
319
- str(row.get("기관유형", "")),
320
- str(row.get("기관명", "")),
321
- str(row.get("이용시작일", "")),
322
- str(row.get("주요상태", "")),
323
- str(row.get("보호자명", "")),
324
- str(row.get("보호자연락처", "")),
325
- "이용중",
326
- now,
327
- now
328
- ))
329
-
330
- conn.commit()
331
- conn.close()
332
- st.success("엑셀 자료가 DB에 저장되었습니다.")
333
-
334
- except Exception as e:
335
- st.error(f"엑셀 업로드 중 오류가 발생했습니다: {e}")
336
-
337
- # -----------------------------
338
- # 수정 / 삭제
339
- # -----------------------------
340
- elif menu == "수정 / 삭제":
341
- st.subheader("✏️ 수급자 정보 수정 / 삭제")
342
-
343
- conn = get_conn()
344
- df = pd.read_sql_query("SELECT id, name, masked_name, care_grade, institution_name FROM clients ORDER BY id DESC", conn)
345
- conn.close()
346
-
347
- if df.empty:
348
- st.info("수정할 수급자가 없습니다.")
349
- else:
350
- options = df.apply(
351
- lambda x: f"{x['id']}번 - {x['masked_name']} / {x['care_grade']} / {x['institution_name']}",
352
- axis=1
353
- ).tolist()
354
-
355
- selected = st.selectbox("수정할 수급자 선택", options)
356
- selected_id = int(selected.split("번")[0])
357
-
358
- conn = get_conn()
359
- client = pd.read_sql_query("SELECT * FROM clients WHERE id = ?", conn, params=(selected_id,))
360
- conn.close()
361
-
362
- if not client.empty:
363
- c = client.iloc[0]
364
-
365
- with st.form("edit_form"):
366
- col1, col2, col3 = st.columns(3)
367
-
368
- with col1:
369
- name = st.text_input("수급자 이름", value=c["name"])
370
- gender = st.selectbox("성별", ["여", "남", "기타"], index=["여", "남", "기타"].index(c["gender"]) if c["gender"] in ["여", "남", "기타"] else 0)
371
- birth_year = st.text_input("출생연도", value=c["birth_year"])
372
-
373
- with col2:
374
- grade_options = ["1등급", "2등급", "3등급", "4등급", "5등급", "인지지원등급", "등급외", "미입력"]
375
- care_grade = st.selectbox(
376
- "장기요양등급",
377
- grade_options,
378
- index=grade_options.index(c["care_grade"]) if c["care_grade"] in grade_options else 7
379
- )
380
- institution_type = st.text_input("기관 유형", value=c["institution_type"])
381
- institution_name = st.text_input("기관명", value=c["institution_name"])
382
-
383
- with col3:
384
- admission_date = st.text_input("이용 시작일 / 입소일", value=c["admission_date"])
385
- status = st.selectbox(
386
- "상태",
387
- ["이용중", "입소중", "퇴소", "중지", "사망"],
388
- index=["이용중", "입소중", "퇴소", "중지", "사망"].index(c["status"]) if c["status"] in ["이용중", "입소중", "퇴소", "중지", "사망"] else 0
389
- )
390
-
391
- main_condition = st.text_area("주요 질환 / 상태", value=c["main_condition"])
392
- cognitive_status = st.text_area("인지 상태", value=c["cognitive_status"])
393
- mobility_status = st.text_area("이동 상태", value=c["mobility_status"])
394
- diet_status = st.text_area("식사 상태", value=c["diet_status"])
395
- toileting_status = st.text_area("배변 / 배뇨 상태", value=c["toileting_status"])
396
-
397
- guardian_name = st.text_input("보호자 이름", value=c["guardian_name"])
398
- guardian_phone = st.text_input("보호자 연락처", value=c["guardian_phone"])
399
- notes = st.text_area("특이사항 / 메모", value=c["notes"])
400
-
401
- save_btn = st.form_submit_button("수정 저장")
402
-
403
- if save_btn:
404
- conn = get_conn()
405
- cur = conn.cursor()
406
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
407
-
408
- cur.execute("""
409
- UPDATE clients
410
- SET name=?, masked_name=?, gender=?, birth_year=?, care_grade=?,
411
- institution_type=?, institution_name=?, admission_date=?,
412
- main_condition=?, cognitive_status=?, mobility_status=?,
413
- diet_status=?, toileting_status=?, guardian_name=?,
414
- guardian_phone=?, notes=?, status=?, updated_at=?
415
- WHERE id=?
416
- """, (
417
- name,
418
- mask_name(name),
419
- gender,
420
- birth_year,
421
- care_grade,
422
- institution_type,
423
- institution_name,
424
- admission_date,
425
- main_condition,
426
- cognitive_status,
427
- mobility_status,
428
- diet_status,
429
- toileting_status,
430
- guardian_name,
431
- guardian_phone,
432
- notes,
433
- status,
434
- now,
435
- selected_id
436
- ))
437
-
438
- conn.commit()
439
- conn.close()
440
- st.success("수급자 정보가 수정되었습니다.")
441
-
442
- st.divider()
443
-
444
- if st.button("⚠️ 이 수급자 삭제하기"):
445
- conn = get_conn()
446
- cur = conn.cursor()
447
- cur.execute("DELETE FROM clients WHERE id = ?", (selected_id,))
448
- conn.commit()
449
- conn.close()
450
- st.warning("수급자 정보가 삭제되었습니다.")