Soufianesejjari commited on
Commit
f997d4a
·
1 Parent(s): 9bc9256

better design

Browse files
Files changed (1) hide show
  1. app.py +203 -115
app.py CHANGED
@@ -28,54 +28,139 @@ logger = logging.getLogger(__name__)
28
  profile_extractor=pe.ProfileExtractor()
29
  grammar_corrector=gc.GrammarCorrector()
30
  def collect_missing_data(profile):
31
- """
32
- Collects missing data from user input when automatic extraction fails.
33
-
34
- Args:
35
- profile: The profile object with potentially missing data
36
-
37
- Returns:
38
- Updated profile object
39
- """
40
- st.subheader("Complete Your Profile")
41
- st.write("Please fill in any missing information below:")
42
 
43
- # Profile image upload
44
- st.subheader("Profile Image")
45
- uploaded_file = st.file_uploader("Upload a profile image (optional)", type=["jpg", "jpeg", "png"])
46
- if uploaded_file is not None:
47
- # Convert the file to base64 for storage
48
- bytes_data = uploaded_file.getvalue()
49
- encoded = base64.b64encode(bytes_data).decode()
50
- profile.profileImg = f"data:image/{uploaded_file.type.split('/')[-1]};base64,{encoded}"
51
- st.image(uploaded_file, caption="Profile Image Preview", width=150)
52
 
53
- # Essential information
54
- st.subheader("Basic Information")
55
- profile.name = st.text_input("Your Full Name:", value=profile.name if profile.name != "N/A" else "")
56
- profile.title = st.text_input("Your Professional Title:", value=profile.title if profile.title != "N/A" else "")
57
- profile.email = st.text_input("Your Email Address:", value=profile.email if profile.email != "N/A" else "")
58
- profile.bio = st.text_area("Professional Bio (50-100 words):", value=profile.bio if profile.bio != "N/A" else "")
59
 
60
- if profile.bio and profile.bio != "N/A":
61
- if st.button("Improve Bio Grammar"):
62
- profile.bio = grammar_corrector.correct_grammar(profile.bio)
63
- st.success("Grammar corrected!")
64
 
65
- # Optional information
66
- profile.tagline = st.text_input("Professional Tagline (short catchy phrase):", value=profile.tagline if profile.tagline else "")
67
 
68
- # Social media
69
- if not profile.social:
70
- profile.social = SocialMedia()
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
- st.subheader("Social Media Links")
73
- profile.social.linkedin = st.text_input("LinkedIn URL:", value=profile.social.linkedin if profile.social and profile.social.linkedin else "")
74
- profile.social.github = st.text_input("GitHub URL:", value=profile.social.github if profile.social and profile.social.github else "")
75
- profile.social.instagram = st.text_input("Instagram URL:", value=profile.social.instagram if profile.social and profile.social.instagram else "")
76
-
77
- # Education
78
- st.subheader("Education")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  education_data = []
80
 
81
  # Display existing education entries with edit options
@@ -124,9 +209,64 @@ def collect_missing_data(profile):
124
  for edu_data in education_data:
125
  if edu_data["school"]: # Only add if school is provided
126
  profile.educations.append(Education(**edu_data))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- # Projects
129
- st.subheader("Projects")
 
 
 
 
 
130
  project_data = []
131
 
132
  # Display existing projects with edit options
@@ -181,10 +321,8 @@ def collect_missing_data(profile):
181
  for proj_data in project_data:
182
  if proj_data["title"] and proj_data["description"]: # Only add if title and description are provided
183
  profile.projects.append(Project(**proj_data))
184
-
185
- # Skills with categories
186
- st.subheader("Skills")
187
-
188
  # Group existing skills by category
189
  technical_skills = [skill.name for skill in profile.skills if skill.category == Category.TECHNICAL]
190
  soft_skills = [skill.name for skill in profile.skills if skill.category == Category.SOFT_SKILLS]
@@ -222,65 +360,15 @@ def collect_missing_data(profile):
222
  add_skills_by_category(soft_skills_input, Category.SOFT_SKILLS)
223
  add_skills_by_category(domain_skills_input, Category.DOMAIN_KNOWLEDGE)
224
  add_skills_by_category(uncategorized_input, None)
225
-
226
- # Work Experience
227
- st.subheader("Work Experience")
228
- experience_data = []
229
-
230
- # Display existing experience entries with edit options
231
- if profile.experiences:
232
- for i, exp in enumerate(profile.experiences):
233
- st.write(f"Experience #{i+1}")
234
- company = st.text_input(f"Company {i+1}:", value=exp.company, key=f"company_{i}")
235
- position = st.text_input(f"Position {i+1}:", value=exp.position, key=f"position_{i}")
236
- start = st.text_input(f"Start Date {i+1}:", value=exp.startDate, key=f"exp_start_{i}")
237
- end = st.text_input(f"End Date {i+1}:", value=exp.endDate if exp.endDate else "", key=f"exp_end_{i}")
238
- description = st.text_area(f"Description {i+1}:", value=exp.description if exp.description else "", key=f"exp_desc_{i}")
239
-
240
- if company and position: # Only add if company and position are provided
241
- experience_data.append({
242
- "company": company,
243
- "position": position,
244
- "startDate": start,
245
- "endDate": end if end else None,
246
- "description": description if description else None
247
- })
248
-
249
- # Option to add new experience entries
250
- add_experience = st.checkbox("Add more work experience", key="add_exp")
251
- if add_experience:
252
- num_new_exp = st.number_input("Number of additional experiences:", min_value=1, max_value=10, value=1)
253
- offset = len(profile.experiences) if profile.experiences else 0
254
 
255
- for i in range(int(num_new_exp)):
256
- st.write(f"Additional Experience #{i+1}")
257
- company = st.text_input(f"Company:", key=f"new_company_{offset+i}")
258
- position = st.text_input(f"Position:", key=f"new_position_{offset+i}")
259
- start = st.text_input(f"Start Date:", key=f"new_exp_start_{offset+i}")
260
- end = st.text_input(f"End Date:", key=f"new_exp_end_{offset+i}")
261
- description = st.text_area(f"Description:", key=f"new_exp_desc_{offset+i}")
262
-
263
- if company and position: # Only add if company and position are provided
264
- correct_grammar_btn = st.button(f"Correct Grammar for Experience #{i+1}")
265
- if correct_grammar_btn and description:
266
- description = grammar_corrector.correct_grammar(description)
267
- st.success("Grammar corrected!")
268
-
269
- experience_data.append({
270
- "company": company,
271
- "position": position,
272
- "startDate": start,
273
- "endDate": end if end else None,
274
- "description": description if description else None
275
- })
276
-
277
- # Update profile with experience data
278
- profile.experiences = []
279
- for exp_data in experience_data:
280
- if exp_data["company"] and exp_data["position"]: # Only add if company and position are provided
281
- profile.experiences.append(Experience(**exp_data))
282
-
283
- return profile
284
 
285
  def display_profile(profile):
286
  """
@@ -506,6 +594,7 @@ def main():
506
 
507
  # Mark as saved in session state
508
  st.session_state.profile_saved = True
 
509
 
510
  # Display the complete profile
511
  display_profile(profile)
@@ -520,17 +609,16 @@ def main():
520
 
521
  # Final state - allow extracting another profile
522
  else:
523
- st.success("Profile extraction complete!")
 
 
 
524
 
525
- # Show options to extract another profile or view the current one
526
- if st.button("Extract Another Profile"):
527
- # Reset session state
528
- for key in ['profile', 'extraction_complete', 'user_input_complete', 'profile_saved']:
529
- st.session_state[key] = False
530
  st.rerun()
531
- else:
532
- # Show the profile again
533
- display_profile(st.session_state.profile)
534
 
535
  if __name__ == "__main__":
536
  main()
 
28
  profile_extractor=pe.ProfileExtractor()
29
  grammar_corrector=gc.GrammarCorrector()
30
  def collect_missing_data(profile):
31
+ """Collects missing data from user input using a step-by-step form"""
 
 
 
 
 
 
 
 
 
 
32
 
33
+ # Initialize step in session state if not exists
34
+ if 'form_step' not in st.session_state:
35
+ st.session_state.form_step = 1
 
 
 
 
 
 
36
 
37
+ # Progress bar
38
+ total_steps = 6
39
+ progress = st.progress((st.session_state.form_step - 1) / total_steps)
 
 
 
40
 
41
+ # Step navigation
42
+ st.write(f"Step {st.session_state.form_step} of {total_steps}")
 
 
43
 
44
+ # Create columns for navigation buttons
45
+ col1, col2, col3 = st.columns([1, 2, 1])
46
 
47
+ with col1:
48
+ if st.session_state.form_step > 1:
49
+ if st.button("← Previous"):
50
+ st.session_state.form_step -= 1
51
+ st.rerun()
52
+
53
+ with col3:
54
+ if st.session_state.form_step < total_steps:
55
+ if st.button("Next →"):
56
+ st.session_state.form_step += 1
57
+ st.rerun()
58
+
59
+ # Step content
60
+ if st.session_state.form_step == 1:
61
+ st.subheader("📸 Profile Image & Basic Information")
62
 
63
+ # Profile image upload with preview
64
+ uploaded_file = st.file_uploader("Upload a profile image", type=["jpg", "jpeg", "png"])
65
+ if uploaded_file:
66
+ bytes_data = uploaded_file.getvalue()
67
+ encoded = base64.b64encode(bytes_data).decode()
68
+ profile.profileImg = f"data:image/{uploaded_file.type.split('/')[-1]};base64,{encoded}"
69
+ st.image(uploaded_file, caption="Profile Preview", width=150)
70
+
71
+ # Basic info with validation
72
+ profile.name = st.text_input("Full Name*", value=profile.name if profile.name != "N/A" else "",
73
+ help="Enter your full name as you want it to appear on your portfolio")
74
+ if not profile.name:
75
+ st.warning("Name is required")
76
+
77
+ profile.title = st.text_input("Professional Title*", value=profile.title if profile.title != "N/A" else "")
78
+ if not profile.title:
79
+ st.warning("Professional title is required")
80
+
81
+ elif st.session_state.form_step == 2:
82
+ st.subheader("📝 Bio & Contact")
83
+ profile.email = st.text_input("Email Address*", value=profile.email if profile.email != "N/A" else "",
84
+ help="This will be used as your contact email")
85
+
86
+ profile.bio = st.text_area("Professional Bio*", value=profile.bio if profile.bio != "N/A" else "",
87
+ help="Write a brief professional summary (50-100 words)")
88
+
89
+ if profile.bio:
90
+ if st.button("✨ Improve Bio Grammar"):
91
+ profile.bio = grammar_corrector.correct_grammar(profile.bio)
92
+ st.success("Grammar corrected!")
93
+
94
+ elif st.session_state.form_step == 3:
95
+ st.subheader("🎓 Education")
96
+ education_editor(profile)
97
+
98
+ elif st.session_state.form_step == 4:
99
+ st.subheader("💼 Work Experience")
100
+ experience_editor(profile)
101
+
102
+ elif st.session_state.form_step == 5:
103
+ st.subheader("🚀 Projects")
104
+ project_editor(profile)
105
+
106
+ elif st.session_state.form_step == 6:
107
+ st.subheader("🎯 Skills & Social Media")
108
+ skills_editor(profile)
109
+ social_media_editor(profile)
110
+
111
+ return profile
112
+
113
+ def display_success_message(inserted_id, frontend_url):
114
+ """Displays an enhanced success message with portfolio links"""
115
+
116
+ st.balloons() # Add some celebration!
117
+
118
+ success_container = st.container()
119
+ with success_container:
120
+ st.markdown("""
121
+ <div style='padding: 20px; border-radius: 10px; border: 2px solid #28a745; background-color: #f8f9fa;'>
122
+ <h2 style='color: #28a745;'>🎉 Congratulations!</h2>
123
+ <p>Your professional portfolio has been created successfully.</p>
124
+ </div>
125
+ """, unsafe_allow_html=True)
126
+
127
+ st.markdown("### 🔗 Your Portfolio Links")
128
+
129
+ # Portfolio link
130
+ if frontend_url:
131
+ portfolio_url = f"{frontend_url}/{inserted_id}"
132
+ st.markdown(f"""
133
+ - 🌟 **Main Portfolio:** [View Your Portfolio]({portfolio_url})
134
+ - 🆔 **Portfolio ID:** `{inserted_id}`
135
+ """)
136
+
137
+ # API endpoints in expandable section
138
+ with st.expander("🔧 API Endpoints"):
139
+ api_url = f"{settings.PORTFOLIO_URL}/{inserted_id}"
140
+ st.markdown(f"""
141
+ - **Profile Data:** `{api_url}`
142
+ - **Profile Image:** `{api_url}/image`
143
+ """)
144
+
145
+ # Share buttons
146
+ st.markdown("### 📤 Share Your Portfolio")
147
+ col1, col2, col3 = st.columns(3)
148
+ with col1:
149
+ if frontend_url:
150
+ st.markdown(f"""
151
+ <a href="https://twitter.com/intent/tweet?text=Check%20out%20my%20professional%20portfolio!&url={frontend_url}/{inserted_id}" target="_blank">
152
+ Share on Twitter
153
+ </a>
154
+ """, unsafe_allow_html=True)
155
+ with col2:
156
+ if frontend_url:
157
+ st.markdown(f"""
158
+ <a href="https://www.linkedin.com/sharing/share-offsite/?url={frontend_url}/{inserted_id}" target="_blank">
159
+ Share on LinkedIn
160
+ </a>
161
+ """, unsafe_allow_html=True)
162
+
163
+ def education_editor(profile):
164
  education_data = []
165
 
166
  # Display existing education entries with edit options
 
209
  for edu_data in education_data:
210
  if edu_data["school"]: # Only add if school is provided
211
  profile.educations.append(Education(**edu_data))
212
+
213
+ def experience_editor(profile):
214
+ experience_data = []
215
+
216
+ # Display existing experience entries with edit options
217
+ if profile.experiences:
218
+ for i, exp in enumerate(profile.experiences):
219
+ st.write(f"Experience #{i+1}")
220
+ company = st.text_input(f"Company {i+1}:", value=exp.company, key=f"company_{i}")
221
+ position = st.text_input(f"Position {i+1}:", value=exp.position, key=f"position_{i}")
222
+ start = st.text_input(f"Start Date {i+1}:", value=exp.startDate, key=f"exp_start_{i}")
223
+ end = st.text_input(f"End Date {i+1}:", value=exp.endDate if exp.endDate else "", key=f"exp_end_{i}")
224
+ description = st.text_area(f"Description {i+1}:", value=exp.description if exp.description else "", key=f"exp_desc_{i}")
225
+
226
+ if company and position: # Only add if company and position are provided
227
+ experience_data.append({
228
+ "company": company,
229
+ "position": position,
230
+ "startDate": start,
231
+ "endDate": end if end else None,
232
+ "description": description if description else None
233
+ })
234
+
235
+ # Option to add new experience entries
236
+ add_experience = st.checkbox("Add more work experience", key="add_exp")
237
+ if add_experience:
238
+ num_new_exp = st.number_input("Number of additional experiences:", min_value=1, max_value=10, value=1)
239
+ offset = len(profile.experiences) if profile.experiences else 0
240
+
241
+ for i in range(int(num_new_exp)):
242
+ st.write(f"Additional Experience #{i+1}")
243
+ company = st.text_input(f"Company:", key=f"new_company_{offset+i}")
244
+ position = st.text_input(f"Position:", key=f"new_position_{offset+i}")
245
+ start = st.text_input(f"Start Date:", key=f"new_exp_start_{offset+i}")
246
+ end = st.text_input(f"End Date:", key=f"new_exp_end_{offset+i}")
247
+ description = st.text_area(f"Description:", key=f"new_exp_desc_{offset+i}")
248
+
249
+ if company and position: # Only add if company and position are provided
250
+ correct_grammar_btn = st.button(f"Correct Grammar for Experience #{i+1}")
251
+ if correct_grammar_btn and description:
252
+ description = grammar_corrector.correct_grammar(description)
253
+ st.success("Grammar corrected!")
254
+
255
+ experience_data.append({
256
+ "company": company,
257
+ "position": position,
258
+ "startDate": start,
259
+ "endDate": end if end else None,
260
+ "description": description if description else None
261
+ })
262
 
263
+ # Update profile with experience data
264
+ profile.experiences = []
265
+ for exp_data in experience_data:
266
+ if exp_data["company"] and exp_data["position"]: # Only add if company and position are provided
267
+ profile.experiences.append(Experience(**exp_data))
268
+
269
+ def project_editor(profile):
270
  project_data = []
271
 
272
  # Display existing projects with edit options
 
321
  for proj_data in project_data:
322
  if proj_data["title"] and proj_data["description"]: # Only add if title and description are provided
323
  profile.projects.append(Project(**proj_data))
324
+
325
+ def skills_editor(profile):
 
 
326
  # Group existing skills by category
327
  technical_skills = [skill.name for skill in profile.skills if skill.category == Category.TECHNICAL]
328
  soft_skills = [skill.name for skill in profile.skills if skill.category == Category.SOFT_SKILLS]
 
360
  add_skills_by_category(soft_skills_input, Category.SOFT_SKILLS)
361
  add_skills_by_category(domain_skills_input, Category.DOMAIN_KNOWLEDGE)
362
  add_skills_by_category(uncategorized_input, None)
363
+
364
+ def social_media_editor(profile):
365
+ if not profile.social:
366
+ profile.social = SocialMedia()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
+ st.subheader("Social Media Links")
369
+ profile.social.linkedin = st.text_input("LinkedIn URL:", value=profile.social.linkedin if profile.social and profile.social.linkedin else "")
370
+ profile.social.github = st.text_input("GitHub URL:", value=profile.social.github if profile.social and profile.social.github else "")
371
+ profile.social.instagram = st.text_input("Instagram URL:", value=profile.social.instagram if profile.social and profile.social.instagram else "")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
 
373
  def display_profile(profile):
374
  """
 
594
 
595
  # Mark as saved in session state
596
  st.session_state.profile_saved = True
597
+ st.session_state.inserted_id = inserted_id
598
 
599
  # Display the complete profile
600
  display_profile(profile)
 
609
 
610
  # Final state - allow extracting another profile
611
  else:
612
+ display_success_message(
613
+ inserted_id=st.session_state.get('inserted_id'),
614
+ frontend_url=os.environ.get("FRONTEND_URL", "")
615
+ )
616
 
617
+ if st.button("Create Another Profile"):
618
+ for key in ['profile', 'extraction_complete', 'user_input_complete', 'profile_saved', 'form_step']:
619
+ if key in st.session_state:
620
+ del st.session_state[key]
 
621
  st.rerun()
 
 
 
622
 
623
  if __name__ == "__main__":
624
  main()