AreejMehboob commited on
Commit
d667199
·
verified ·
1 Parent(s): 4bd53e5

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +623 -39
src/streamlit_app.py CHANGED
@@ -1,7 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # import os, types, streamlit as st
2
- # import os
 
3
  # os.environ['STREAMLIT_CONFIG_DIR'] = '/tmp/.streamlit'
4
- # # Fetch the hidden code from env var
5
  # app_code = os.environ.get("APP_CODE", "")
6
 
7
  # def execute_code(code_str):
@@ -10,52 +32,576 @@
10
  # exec(code_str, module.__dict__)
11
  # if hasattr(module, "main"):
12
  # module.main()
 
13
  # except Exception as e:
14
  # st.error(f"Error in hidden code: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- # if app_code:
17
- # execute_code(app_code)
 
18
 
19
- # else:
20
- # st.error("APP_CODE is empty. Did you set it?")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
 
 
22
 
23
- import os, types, streamlit as st
24
- import requests # Make sure to import requests if used
25
 
26
- os.environ['STREAMLIT_CONFIG_DIR'] = '/tmp/.streamlit'
27
- app_code = os.environ.get("APP_CODE", "")
28
 
29
- def execute_code(code_str):
30
- module = types.ModuleType("dynamic_app")
31
- try:
32
- exec(code_str, module.__dict__)
33
- if hasattr(module, "main"):
34
- module.main()
35
- return module
36
- except Exception as e:
37
- st.error(f"Error in hidden code: {e}")
38
- return None
39
 
40
- def main():
41
- global job_posts, api_endpoint, hf_token, simulated_code_animation, generate_email, generate_phone_number, generate_linkedin
42
-
43
- if app_code:
44
- module = execute_code(app_code)
45
- if module:
46
- # Extract required variables and functions from the module
47
- job_posts = getattr(module, 'job_posts', [])
48
- api_endpoint = getattr(module, 'api_endpoint', '')
49
- hf_token = getattr(module, 'hf_token', '')
50
- simulated_code_animation = getattr(module, 'simulated_code_animation', lambda x: None)
51
- generate_email = getattr(module, 'generate_email', lambda x: "[email protected]")
52
- generate_phone_number = getattr(module, 'generate_phone_number', lambda: "555-123-4567")
53
- generate_linkedin = getattr(module, 'generate_linkedin', lambda x: "linkedin.com/in/example")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  else:
55
- st.error("APP_CODE is empty. Did you set it?")
56
- return
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
 
59
  st.set_page_config(layout="wide")
60
 
61
  # Sidebar for navigation
@@ -418,8 +964,46 @@ def main():
418
  else:
419
  st.write("No education information available.")
420
 
421
-
422
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  st.markdown("""
424
  <style>
425
  .download-resume-btn {
@@ -470,4 +1054,4 @@ def main():
470
  st.error(f"An error occurred: {str(e)}")
471
 
472
  if __name__ == "__main__":
473
- main()
 
1
+ # # import os, types, streamlit as st
2
+ # # import os
3
+ # # os.environ['STREAMLIT_CONFIG_DIR'] = '/tmp/.streamlit'
4
+ # # # Fetch the hidden code from env var
5
+ # # app_code = os.environ.get("APP_CODE", "")
6
+
7
+ # # def execute_code(code_str):
8
+ # # module = types.ModuleType("dynamic_app")
9
+ # # try:
10
+ # # exec(code_str, module.__dict__)
11
+ # # if hasattr(module, "main"):
12
+ # # module.main()
13
+ # # except Exception as e:
14
+ # # st.error(f"Error in hidden code: {e}")
15
+
16
+ # # if app_code:
17
+ # # execute_code(app_code)
18
+
19
+ # # else:
20
+ # # st.error("APP_CODE is empty. Did you set it?")
21
+
22
+
23
  # import os, types, streamlit as st
24
+ # import requests # Make sure to import requests if used
25
+
26
  # os.environ['STREAMLIT_CONFIG_DIR'] = '/tmp/.streamlit'
 
27
  # app_code = os.environ.get("APP_CODE", "")
28
 
29
  # def execute_code(code_str):
 
32
  # exec(code_str, module.__dict__)
33
  # if hasattr(module, "main"):
34
  # module.main()
35
+ # return module
36
  # except Exception as e:
37
  # st.error(f"Error in hidden code: {e}")
38
+ # return None
39
+
40
+ # def main():
41
+ # global job_posts, api_endpoint, hf_token, simulated_code_animation, generate_email, generate_phone_number, generate_linkedin
42
+
43
+ # if app_code:
44
+ # module = execute_code(app_code)
45
+ # if module:
46
+ # # Extract required variables and functions from the module
47
+ # job_posts = getattr(module, 'job_posts', [])
48
+ # api_endpoint = getattr(module, 'api_endpoint', '')
49
+ # hf_token = getattr(module, 'hf_token', '')
50
+ # simulated_code_animation = getattr(module, 'simulated_code_animation', lambda x: None)
51
+ # generate_email = getattr(module, 'generate_email', lambda x: "[email protected]")
52
+ # generate_phone_number = getattr(module, 'generate_phone_number', lambda: "555-123-4567")
53
+ # generate_linkedin = getattr(module, 'generate_linkedin', lambda x: "linkedin.com/in/example")
54
+ # else:
55
+ # st.error("APP_CODE is empty. Did you set it?")
56
+ # return
57
+
58
+
59
+ # st.set_page_config(layout="wide")
60
+
61
+ # # Sidebar for navigation
62
+ # with st.sidebar:
63
+ # # About section with blue background
64
+ # st.markdown("""
65
+ # <div style="background-color:#3299a8; padding:10px; border-radius:5px;">
66
+ # <h3 style="color:white;">About</h3>
67
+ # <p style="color:white;">
68
+ # This Resume Matching System helps you find the best candidates for your job openings.
69
+ # Simply input your job description and requirements, and our AI-powered system will
70
+ # analyze and rank resumes based on skill match, experience, and overall fit.
71
+ # </p>
72
+ # </div>
73
+ # """, unsafe_allow_html=True)
74
+
75
+ # # How it Works section with light blue background
76
+ # st.markdown("""
77
+ # <div style="background-color:#e6f3f5; padding:10px; border-radius:5px; margin-top:10px;">
78
+ # <h3 style="color:#3299a8;">How it Works</h3>
79
+ # <ul style="margin-left: 15px; padding-left: 10px;">
80
+ # <li>Enter your job description or select a sample</li>
81
+ # <li>Our AI-agent analyzes key skills and requirements</li>
82
+ # <li>View ranked candidates with match percentages</li>
83
+ # <li>Examine detailed skill comparisons for each resume</li>
84
+ # </ul>
85
+ # </div>
86
+ # """, unsafe_allow_html=True)
87
+
88
+ # # Sample Job Descriptions section
89
+ # st.markdown("<h3 style='font-size:1.2em;'>Sample Job Descriptions</h3>", unsafe_allow_html=True)
90
+
91
+ # # Display sample job descriptions in sidebar with smaller font
92
+ # st.write("Click any job to prefill the form:")
93
+
94
+ # # Create a container with custom CSS for smaller buttons
95
+ # st.markdown("""
96
+ # <style>
97
+ # div.stButton > button {
98
+ # font-size: 0.8em;
99
+ # padding: 2px 8px;
100
+ # margin: 3px 0px;
101
+ # width: 100%;
102
+ # text-align: left;
103
+ # }
104
+ # .resume-card {
105
+ # background-color: #f8f9fa;
106
+ # border-radius: 10px;
107
+ # padding: 15px;
108
+ # margin-bottom: 20px;
109
+ # box-shadow: 0 4px 6px rgba(0,0,0,0.1);
110
+ # }
111
+ # .card-header {
112
+ # border-bottom: 1px solid #e0e0e0;
113
+ # padding-bottom: 10px;
114
+ # margin-bottom: 15px;
115
+ # }
116
+ # .contact-section {
117
+ # background-color: #e6f3f5;
118
+ # padding: 10px;
119
+ # border-radius: 5px;
120
+ # margin-top: 10px;
121
+ # }
122
+ # .skill-badge {
123
+ # background-color: #3299a8;
124
+ # color: white;
125
+ # padding: 4px 8px;
126
+ # border-radius: 15px;
127
+ # margin: 2px;
128
+ # display: inline-block;
129
+ # font-size: 0.85em;
130
+ # }
131
+ # .missing-skill-badge {
132
+ # background-color: #6c757d;
133
+ # color: white;
134
+ # padding: 4px 8px;
135
+ # border-radius: 15px;
136
+ # margin: 2px;
137
+ # display: inline-block;
138
+ # font-size: 0.85em;
139
+ # }
140
+ # .experience-card {
141
+ # background-color: #f8f9fa;
142
+ # border-left: 3px solid #3299a8;
143
+ # padding: 10px;
144
+ # margin-bottom: 10px;
145
+ # border-radius: 0 5px 5px 0;
146
+ # }
147
+ # </style>
148
+ # """, unsafe_allow_html=True)
149
+
150
+ # # Add horizontal line before job listings
151
+ # st.markdown("<hr>", unsafe_allow_html=True)
152
+
153
+ # # Job buttons
154
+ # for i, job in enumerate(job_posts):
155
+ # if st.button(job["title"], key=f"job_{i}"):
156
+ # # This will be used to set the job description text area
157
+ # st.session_state.job_description = job["jd"]
158
+
159
+ # # Main content area
160
+ # st.title("Resume Matching System")
161
+
162
+ # # Initialize session state for job description if it doesn't exist
163
+ # if 'job_description' not in st.session_state:
164
+ # st.session_state.job_description = "Enter job description here..."
165
 
166
+ # # Input fields - using session state for job description
167
+ # job_description = st.text_area("Job Description", value=st.session_state.job_description, height=250)
168
+ # additional_requirements = st.text_area("Additional Requirements", "", height=100)
169
 
170
+ # # Create two columns for the numeric inputs
171
+ # limit = st.slider("Number of Results", min_value=1, max_value=10, value=5, step=1)
172
+
173
+ # # Search button and animation container
174
+ # search_button = st.button("Search Resumes", type="primary")
175
+
176
+ # # Create a container for the code animation
177
+ # code_container = st.container()
178
+
179
+ # # Add custom CSS for the code animation box
180
+ # st.markdown("""
181
+ # <style>
182
+ # .highlight {
183
+ # background-color: black !important;
184
+ # }
185
+ # .highlight pre {
186
+ # color: yellow !important;
187
+ # }
188
+ # .highlight .gp, .highlight .gu, .highlight .gt {
189
+ # color: yellow !important;
190
+ # }
191
+ # pre code {
192
+ # white-space: pre-wrap !important;
193
+ # }
194
+ # </style>
195
+ # """, unsafe_allow_html=True)
196
+ # st.markdown("""
197
+ # <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
198
+ # """, unsafe_allow_html=True)
199
+ # if search_button:
200
+
201
+ # # Prepare the API request
202
+
203
+ # url = f"{api_endpoint}/resumes/search"
204
+ # headers = {
205
+ # "accept": "application/json",
206
+ # "Content-Type": "application/json",
207
+ # "Authorization": hf_token
208
+ # }
209
+ # payload = {
210
+ # "job_description": job_description,
211
+ # "additional_requirements": additional_requirements,
212
+ # "limit": limit,
213
+ # }
214
+
215
+ # try:
216
+ # # Display the animation while waiting
217
+ # with code_container:
218
+ # # Create the black box with yellow code animation
219
+ # code_display = simulated_code_animation(code_container)
220
+ # import time
221
+ # strt_time=time.time()
222
+ # # Make the API request
223
+ # response = requests.post(url, headers=headers, json=payload)
224
+ # print(f"total time taken by fast api to generate answer: {time.time()-strt_time}")
225
+ # # Clear the code animation
226
+ # code_container.empty()
227
+
228
+ # if response.status_code == 200:
229
+ # # Process successful response
230
+ # data = response.json()
231
+ # st.success(f"Found {data['count']} matching resumes")
232
+
233
+ # # Display each resume with the new card-based layout
234
+ # for i, resume in enumerate(data['results']):
235
+ # resume_data = resume['resume_data']
236
+ # explainability = resume['explainibility']
237
+ # # Generate synthetic contact information
238
+ # full_name = resume_data.get('full_name', 'No Name')
239
+ # # Add synthetic data to resume_data if not present
240
+ # if 'email' not in resume_data and 'email_id' not in resume_data:
241
+ # resume_data['email'] = generate_email(full_name)
242
+ # if 'phone' not in resume_data:
243
+ # resume_data['phone'] = generate_phone_number()
244
+ # if 'linkedin_profile' not in resume_data and 'linkedin' not in resume_data:
245
+ # resume_data['linkedin'] = generate_linkedin(full_name)
246
+
247
+ # # Main card with essential information
248
+ # with st.container():
249
+ # col1, col2 = st.columns([7, 3])
250
+
251
+ # with col1:
252
+ # # Name with larger font and accent color
253
+ # st.markdown(f"""
254
+ # <h2 style="color:#2C3E50; font-size:28px; margin-bottom:5px;">
255
+ # {full_name}
256
+ # </h2>
257
+ # """, unsafe_allow_html=True)
258
+
259
+ # # Years of experience with an icon
260
+ # years_exp = resume_data.get('total_experience_years', 'Not specified')
261
+ # st.markdown(f"""
262
+ # <div style="margin-bottom:15px;">
263
+ # <span style="color:#3299a8; font-size:16px;">
264
+ # <i class="fas fa-briefcase"></i> <strong>Years of Experience:</strong>
265
+ # </span>
266
+ # <span style="font-size:16px;">{years_exp}</span>
267
+ # </div>
268
+ # """, unsafe_allow_html=True)
269
+
270
+ # # Summary in a nice box with a border
271
+ # summary = ""
272
+ # if 'overall_summary' in resume:
273
+ # summary = resume.get('overall_summary')
274
+ # elif isinstance(resume_data.get('summary'), str):
275
+ # summary = resume_data.get('summary')
276
+
277
+ # st.markdown(explainability)
278
+
279
+ # if summary:
280
+ # st.markdown(f"""
281
+ # <div style="border-left:4px solid #3299a8; padding-left:15px;
282
+ # background-color:#f8f9fa; padding:10px; border-radius:0 5px 5px 0;">
283
+ # <div style="color:#3299a8; font-weight:bold; margin-bottom:5px;">SUMMARY</div>
284
+ # <div style="font-size:15px; line-height:1.5;">{summary}</div>
285
+ # </div>
286
+ # """, unsafe_allow_html=True)
287
+ # st.markdown("<br>", unsafe_allow_html=True)
288
+ # with col2:
289
+ # # Contact card with background
290
+ # st.markdown("""
291
+ # <div style="background-color:#f0f7fa; border-radius:8px; padding:15px;
292
+ # box-shadow:0 2px 5px rgba(0,0,0,0.05); margin-bottom:15px;">
293
+ # <h3 style="color:#3299a8; font-size:18px; border-bottom:2px solid #3299a8;
294
+ # padding-bottom:8px; margin-top:0;">
295
+ # <i class="fas fa-address-card"></i> CONTACT INFORMATION
296
+ # </h3>
297
+ # """, unsafe_allow_html=True)
298
+
299
+ # # Email with icon
300
+ # email = resume_data.get('email', resume_data.get('email_id', 'Not provided'))
301
+ # st.markdown(f"""
302
+ # <div style="margin-bottom:10px;">
303
+ # <i class="fas fa-envelope" style="color:#3299a8; width:20px;"></i>
304
+ # <strong style="color:#555;">Email:</strong><br>
305
+ # <a href="mailto:{email}" style="text-decoration:none; color:#3299a8;
306
+ # margin-left:25px; display:block; margin-top:3px;">{email}</a>
307
+ # </div>
308
+ # """, unsafe_allow_html=True)
309
+
310
+ # # Phone with icon
311
+ # phone = resume_data.get('phone', 'Not provided')
312
+ # st.markdown(f"""
313
+ # <div style="margin-bottom:10px;">
314
+ # <i class="fas fa-phone" style="color:#3299a8; width:20px;"></i>
315
+ # <strong style="color:#555;">Phone:</strong><br>
316
+ # <span style="margin-left:25px; display:block; margin-top:3px;">{phone}</span>
317
+ # </div>
318
+ # """, unsafe_allow_html=True)
319
+
320
+ # # Location with icon
321
+ # location = resume_data.get('location', 'Not specified')
322
+ # st.markdown(f"""
323
+ # <div style="margin-bottom:10px;">
324
+ # <i class="fas fa-map-marker-alt" style="color:#3299a8; width:20px;"></i>
325
+ # <strong style="color:#555;">Location:</strong><br>
326
+ # <span style="margin-left:25px; display:block; margin-top:3px;">{location}</span>
327
+ # </div>
328
+ # """, unsafe_allow_html=True)
329
+
330
+ # # LinkedIn with icon
331
+ # linkedin_url = resume_data.get('linkedin_profile', resume_data.get('linkedin', 'Not provided'))
332
+ # st.markdown(f"""
333
+ # <div style="margin-bottom:5px;">
334
+ # <i class="fab fa-linkedin" style="color:#3299a8; width:20px;"></i>
335
+ # <strong style="color:#555;">LinkedIn:</strong><br>
336
+ # <a href="{linkedin_url}" target="_blank" style="text-decoration:none;
337
+ # color:#3299a8; margin-left:25px; display:block; margin-top:3px;
338
+ # white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;">
339
+ # {linkedin_url.replace('https://', '')}
340
+ # </a>
341
+ # </div>
342
+ # </div>
343
+ # """, unsafe_allow_html=True)
344
+
345
+ # # Create expandable sections for details - MOVED INSIDE THE LOOP
346
+ # with st.expander(f"Resume Content for {full_name}", expanded=False):
347
+ # tabs = st.tabs(["All Skills", "Experience", "Projects", "Education"])
348
+
349
+ # # All Skills tab
350
+ # with tabs[0]:
351
+ # st.subheader("Skills")
352
+ # if 'skills' in resume_data and resume_data['skills']:
353
+ # skills_html = ""
354
+ # for skill in resume_data['skills']:
355
+ # # Check if this skill is in matched_skills
356
+ # is_matched = skill in resume.get('matched_skills', [])
357
+ # badge_class = "skill-badge" if is_matched else "missing-skill-badge"
358
+ # skills_html += f'<span class="{badge_class}">{skill}</span> '
359
+ # st.markdown(skills_html, unsafe_allow_html=True)
360
+ # else:
361
+ # st.write("No skills listed.")
362
+
363
+ # # Experiences tab
364
+ # with tabs[1]:
365
+ # st.subheader("Professional Experience")
366
+ # if 'experience' in resume_data and resume_data['experience']:
367
+ # for exp in resume_data['experience']:
368
+ # with st.container():
369
+ # st.markdown(f"""
370
+ # <div class="experience-card">
371
+ # <strong>{exp.get('title', 'Position')}</strong> at <strong>{exp.get('company', 'Company')}</strong>
372
+ # <br><em>{exp.get('duration', '')}</em>
373
+ # <p>{exp.get('description', '')}</p>
374
+ # </div>
375
+ # """, unsafe_allow_html=True)
376
+ # elif 'professional_experiences' in resume_data and resume_data['professional_experiences']:
377
+ # for exp in resume_data['professional_experiences']:
378
+ # with st.container():
379
+ # st.markdown(f"""
380
+ # <div class="experience-card">
381
+ # <strong>{exp.get('title', 'Position')}</strong> at <strong>{exp.get('company', 'Company')}</strong>
382
+ # <br><em>{exp.get('duration', '')}</em>
383
+ # <p>{exp.get('description', '')}</p>
384
+ # </div>
385
+ # """, unsafe_allow_html=True)
386
+ # else:
387
+ # st.write("No experience information available.")
388
+
389
+ # # Projects tab
390
+ # with tabs[2]:
391
+ # st.subheader("Projects")
392
+ # if 'projects' in resume_data and resume_data['projects']:
393
+ # for project in resume_data['projects']:
394
+ # if isinstance(project, dict):
395
+ # project_name = project.get('name', project.get('title', 'Project'))
396
+ # project_desc = project.get('description', '')
397
+ # st.markdown(f"**{project_name}**")
398
+ # st.markdown(f"{project_desc}")
399
+ # st.markdown("---")
400
+ # else:
401
+ # st.markdown(f"- {project}")
402
+ # else:
403
+ # st.write("No projects listed.")
404
+
405
+ # # Education tab
406
+ # with tabs[3]:
407
+ # st.subheader("Education")
408
+ # if 'education' in resume_data and resume_data['education']:
409
+ # for edu in resume_data['education']:
410
+ # with st.container():
411
+ # st.markdown(f"""
412
+ # <div class="experience-card">
413
+ # <strong>{edu.get('degree', 'Degree')}</strong>
414
+ # <br><strong>{edu.get('institution', 'Institution')}</strong>
415
+ # <br><em>{edu.get('date', '')}</em>
416
+ # </div>
417
+ # """, unsafe_allow_html=True)
418
+ # else:
419
+ # st.write("No education information available.")
420
+
421
+
422
+
423
+ # st.markdown("""
424
+ # <style>
425
+ # .download-resume-btn {
426
+ # display: inline-block;
427
+ # width: 100%;
428
+ # background-color: #3299a8;
429
+ # color: white;
430
+ # text-align: center;
431
+ # padding: 12px 20px;
432
+ # margin: 8px 0 25px 0;
433
+ # border-radius: 5px;
434
+ # border: none;
435
+ # cursor: pointer;
436
+ # font-size: 16px;
437
+ # font-weight: 500;
438
+ # transition: all 0.3s ease;
439
+ # text-decoration: none;
440
+ # box-shadow: 0 2px 5px rgba(0,0,0,0.1);
441
+ # }
442
+
443
+ # .download-resume-btn:hover {
444
+ # background-color: #277a86;
445
+ # box-shadow: 0 4px 8px rgba(0,0,0,0.2);
446
+ # transform: translateY(-2px);
447
+ # }
448
+
449
+ # .download-resume-btn i {
450
+ # margin-right: 10px;
451
+ # }
452
+ # </style>
453
+ # """, unsafe_allow_html=True)
454
+
455
+ # # Create a centered container for the download button
456
+ # col1, col2, col3 = st.columns([1, 2, 1])
457
+ # with col2:
458
+ # # Render the download button with icon
459
+ # st.markdown(f"""
460
+ # <button class="download-resume-btn" onclick="alert('This is a demo feature. In a production environment, this would download the resume for {full_name}.')">
461
+ # <i class="fas fa-file-download"></i> Download Resume
462
+ # </button>
463
+ # """, unsafe_allow_html=True)
464
+
465
+ # # Add a separator between resumes
466
+ # st.markdown("---")
467
+ # except Exception as e:
468
+ # # Clear the code animation in case of error
469
+ # code_container.empty()
470
+ # st.error(f"An error occurred: {str(e)}")
471
 
472
+ # if __name__ == "__main__":
473
+ # main()
474
 
 
 
475
 
 
 
476
 
477
+ import streamlit as st
478
+ import requests
479
+ import random
480
+ from sample_jobs import job_posts
 
 
 
 
 
 
481
 
482
+ from dotenv import load_dotenv
483
+ import os
484
+
485
+ load_dotenv()
486
+
487
+ api_endpoint = os.getenv("api_endpoint")
488
+ hf_token = os.getenv("hf_token")
489
+
490
+ import time
491
+
492
+ def simulated_code_animation(container):
493
+ """Displays a simulated code loading animation in a container - one line at a time"""
494
+ code_snippets = [
495
+ "Initializing resume agent",
496
+ "Initializing resume agent.",
497
+ "Initializing resume agent..",
498
+ "Initializing resume agent...",
499
+ "Vectorizing job description",
500
+ "Vectorizing job description.",
501
+ "Vectorizing job description..",
502
+ "Vectorizing job description...",
503
+ "Connecting to database",
504
+ "Connecting to database.",
505
+ "Connecting to database..",
506
+ "Connecting to database...",
507
+ "Database connected!",
508
+ "Database connected!",
509
+ "Database connected!",
510
+ "Database connected!",
511
+ "Choosing correct database of resumes",
512
+ "Choosing correct database of resumes.",
513
+ "Choosing correct database of resumes..",
514
+ "Choosing correct database of resumes...",
515
+ "Matching job description to resumes",
516
+ "Matching job description to resumes.",
517
+ "Matching job description to resumes..",
518
+ "Matching job description to resumes...",
519
+ "Ranking fetched resumes",
520
+ "Ranking fetched resumes.",
521
+ "Ranking fetched resumes..",
522
+ "Ranking fetched resumes...",
523
+ "Generating explanations",
524
+ "Generating explanations.",
525
+ "Generating explanations..",
526
+ "Generating explanations...",
527
+ "Resumes coming up!"
528
+ ]
529
+
530
+ # Add custom CSS for the text display
531
+ container.markdown("""
532
+ <style>
533
+ .terminal-text {
534
+ background-color: black;
535
+ color: #ffff00;
536
+ font-family: monospace;
537
+ font-size: 18px;
538
+ padding: 15px;
539
+ border-radius: 5px;
540
+ margin: 10px 0;
541
+ line-height: 1.5;
542
+ white-space: pre;
543
+ overflow: auto;
544
+ }
545
+ </style>
546
+ """, unsafe_allow_html=True)
547
+
548
+ terminal_placeholder = container.empty()
549
+ progress_bar = container.progress(0)
550
+
551
+ total_steps = len(code_snippets)
552
+
553
+ for idx, line in enumerate(code_snippets):
554
+ # Update progress bar
555
+ progress_value = idx / (total_steps - 1)
556
+ progress_bar.progress(progress_value)
557
+
558
+ # Update terminal text
559
+ terminal_placeholder.markdown(f'<div class="terminal-text">{line}</div>', unsafe_allow_html=True)
560
+ time.sleep(0.85)
561
+
562
+ # Ensure progress bar reaches 100% at the end
563
+ progress_bar.progress(1.0)
564
+
565
+ return terminal_placeholder
566
+
567
+
568
+ def generate_phone_number():
569
+ """Generate a random US phone number with +1 prefix"""
570
+ area_code = random.randint(200, 999)
571
+ middle_three = random.randint(100, 999)
572
+ last_four = random.randint(1000, 9999)
573
+ return f"+1 ({area_code}) {middle_three}-{last_four}"
574
+
575
+ def generate_email(full_name):
576
+ """Generate email from full name"""
577
+ if not full_name or full_name == 'No Name':
578
+ return "[email protected]"
579
+
580
+ # Clean and format the name
581
+ name_parts = full_name.lower().strip().split()
582
+ if len(name_parts) >= 2:
583
+ first_name = name_parts[0]
584
+ last_name = name_parts[-1]
585
+ return f"{first_name}.{last_name}@gmail.com"
586
  else:
587
+ return f"{name_parts[0]}@gmail.com"
 
588
 
589
+ def generate_linkedin(full_name):
590
+ """Generate LinkedIn URL from full name"""
591
+ if not full_name or full_name == 'No Name':
592
+ return "https://linkedin.com/in/professional-profile"
593
+
594
+ # Clean and format the name
595
+ name_parts = full_name.lower().strip().split()
596
+ if len(name_parts) >= 2:
597
+ first_name = name_parts[0]
598
+ last_name = name_parts[-1]
599
+ suffix = random.randint(10, 999) if random.random() < 0.3 else ""
600
+ return f"https://linkedin.com/in/{first_name}-{last_name}{suffix}"
601
+ else:
602
+ return f"https://linkedin.com/in/{name_parts[0]}-profile"
603
 
604
+ def main():
605
  st.set_page_config(layout="wide")
606
 
607
  # Sidebar for navigation
 
964
  else:
965
  st.write("No education information available.")
966
 
967
+ # # Accomplishments tab
968
+ # with tabs[4]:
969
+ # st.subheader("Accomplishments")
970
+ # if 'accomplishments' in resume_data and resume_data['accomplishments']:
971
+ # for accomplishment in resume_data['accomplishments']:
972
+ # if isinstance(accomplishment, str):
973
+ # st.markdown(f"- {accomplishment}")
974
+ # elif isinstance(accomplishment, dict):
975
+ # # Handle if accomplishments are stored as dictionary objects
976
+ # title = accomplishment.get('title', 'Accomplishment')
977
+ # description = accomplishment.get('description', '')
978
+ # st.markdown(f"**{title}**")
979
+ # if description:
980
+ # st.markdown(f"{description}")
981
+ # st.markdown("---")
982
+ # else:
983
+ # st.write("No accomplishments listed.")
984
+
985
+ # # Certifications tab
986
+ # with tabs[5]:
987
+ # st.subheader("Certifications")
988
+ # if 'certifications' in resume_data and resume_data['certifications']:
989
+ # for cert in resume_data['certifications']:
990
+ # if isinstance(cert, str):
991
+ # st.markdown(f"- {cert}")
992
+ # elif isinstance(cert, dict):
993
+ # # Handle if certifications are stored as dictionary objects
994
+ # name = cert.get('name', cert.get('title', 'Certification'))
995
+ # issuer = cert.get('issuer', cert.get('organization', ''))
996
+ # date = cert.get('date', cert.get('issued_date', ''))
997
+ # st.markdown(f"**{name}**")
998
+ # if issuer:
999
+ # st.markdown(f"Issuer: {issuer}")
1000
+ # if date:
1001
+ # st.markdown(f"Date: {date}")
1002
+ # st.markdown("---")
1003
+ # else:
1004
+ # st.write("No certifications listed.")
1005
+
1006
+ # Add the download button after each resume
1007
  st.markdown("""
1008
  <style>
1009
  .download-resume-btn {
 
1054
  st.error(f"An error occurred: {str(e)}")
1055
 
1056
  if __name__ == "__main__":
1057
+ main()