husseinelsaadi commited on
Commit
5c64dc0
·
1 Parent(s): 5fed273

templates updated

Browse files
backend/templates/apply.html CHANGED
@@ -35,6 +35,17 @@
35
  <label for="resume">Upload Resume</label>
36
  <!-- Resume upload remains mandatory. The file will be stored for recruiter review but is no longer parsed automatically. -->
37
  <input type="file" name="resume" id="resume" class="form-control" required accept=".pdf,.doc,.docx">
 
 
 
 
 
 
 
 
 
 
 
38
  </div>
39
 
40
  <!--
@@ -56,21 +67,8 @@
56
  <textarea name="education" id="education" class="form-control" rows="3" placeholder="e.g. B.Sc. in Computer Science, M.Sc. in Data Science" required></textarea>
57
  </div>
58
 
59
- <!-- Interview guidelines displayed directly above the submit button. These
60
- instructions help applicants prepare for the AI interview. They are
61
- intentionally placed within the form so that they appear close to
62
- the submit action, ensuring visibility without disrupting the flow
63
- of the application fields. -->
64
- <div class="interview-guidelines" style="background-color: #f8f9fa; border-left: 4px solid var(--primary); padding: 1rem; margin-top: 1.5rem; border-radius: 6px;">
65
- <h3 style="margin-top: 0; color: var(--primary); margin-bottom: 0.75rem;">Important Interview Guidelines</h3>
66
- <ul style="margin-left: 1rem; padding-left: 1rem; list-style-type: disc; line-height: 1.5;">
67
- <li>The interview can be taken only once, so please be prepared.</li>
68
- <li>Make sure you are in a quiet environment with a stable internet connection.</li>
69
- <li>This is not a final job interview, but it helps the company shortlist the most relevant candidates.</li>
70
- <li>The interview is customized based on your CV and the job requirements.</li>
71
- <li>It takes 10 to 15 minutes and includes both general and skill-based questions.</li>
72
- </ul>
73
- </div>
74
 
75
  <div class="application-actions" style="margin-top: 2rem;">
76
  <button type="submit" class="btn btn-primary">Submit Application</button>
@@ -117,5 +115,62 @@
117
  .btn-primary:hover {
118
  opacity: 0.9;
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  {% endblock %}
 
35
  <label for="resume">Upload Resume</label>
36
  <!-- Resume upload remains mandatory. The file will be stored for recruiter review but is no longer parsed automatically. -->
37
  <input type="file" name="resume" id="resume" class="form-control" required accept=".pdf,.doc,.docx">
38
+ <!-- Parse Resume button sits beside the upload to allow users to extract information from their CV. It uses a
39
+ type="button" so that clicking it does not submit the form. The actual parsing logic is defined in
40
+ the script at the bottom of this template. -->
41
+ <button type="button" id="parse-resume" class="btn btn-secondary" style="margin-top:0.5rem;">Parse Resume</button>
42
+ </div>
43
+
44
+ <!-- Name field added to capture the applicant's full name. This input can be autofilled by the resume parser,
45
+ but remains editable so applicants can correct any mistakes. -->
46
+ <div class="form-group">
47
+ <label for="full-name">Full Name</label>
48
+ <input type="text" name="full_name" id="full-name" class="form-control" placeholder="e.g. Jane Doe" required>
49
  </div>
50
 
51
  <!--
 
67
  <textarea name="education" id="education" class="form-control" rows="3" placeholder="e.g. B.Sc. in Computer Science, M.Sc. in Data Science" required></textarea>
68
  </div>
69
 
70
+ <!-- Interview guidelines removed from this page. They are now displayed on the
71
+ "My Applications" page so applicants see them before taking the interview. -->
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  <div class="application-actions" style="margin-top: 2rem;">
74
  <button type="submit" class="btn btn-primary">Submit Application</button>
 
115
  .btn-primary:hover {
116
  opacity: 0.9;
117
  }
118
+
119
+ /* Secondary button styling used for the "Parse Resume" control */
120
+ .btn-secondary {
121
+ background: var(--secondary);
122
+ color: white;
123
+ padding: 0.75rem 1.5rem;
124
+ font-weight: 500;
125
+ border: none;
126
+ border-radius: 6px;
127
+ cursor: pointer;
128
+ }
129
+ .btn-secondary:hover {
130
+ opacity: 0.9;
131
+ }
132
  </style>
133
+
134
+ {# Resume parsing script: attaches click handler to the Parse Resume button. It performs an asynchronous
135
+ POST to a placeholder endpoint (`/parse_resume`) with the uploaded file and, upon success,
136
+ populates the corresponding form fields. Users can still edit the populated fields. #}
137
+ <script>
138
+ document.addEventListener('DOMContentLoaded', function() {
139
+ const parseBtn = document.getElementById('parse-resume');
140
+ if (!parseBtn) return;
141
+ parseBtn.addEventListener('click', function() {
142
+ const resumeInput = document.getElementById('resume');
143
+ if (!resumeInput || !resumeInput.files || resumeInput.files.length === 0) {
144
+ alert('Please upload your resume before parsing.');
145
+ return;
146
+ }
147
+ const formData = new FormData();
148
+ formData.append('resume', resumeInput.files[0]);
149
+ fetch('/parse_resume', {
150
+ method: 'POST',
151
+ body: formData
152
+ }).then(resp => resp.json())
153
+ .then(data => {
154
+ if (data) {
155
+ if (data.name && document.getElementById('full-name')) {
156
+ document.getElementById('full-name').value = data.name;
157
+ }
158
+ if (data.skills && document.getElementById('skills')) {
159
+ document.getElementById('skills').value = data.skills;
160
+ }
161
+ if (data.education && document.getElementById('education')) {
162
+ document.getElementById('education').value = data.education;
163
+ }
164
+ if (data.experience && document.getElementById('experience')) {
165
+ document.getElementById('experience').value = data.experience;
166
+ }
167
+ }
168
+ })
169
+ .catch(err => {
170
+ console.error(err);
171
+ alert('Unable to parse resume. Please try again later.');
172
+ });
173
+ });
174
+ });
175
+ </script>
176
  {% endblock %}
backend/templates/base.html CHANGED
@@ -416,7 +416,7 @@
416
  }
417
 
418
  .feature-content h3 {
419
- font-size: 1.5rem;
420
  margin-bottom: 1rem;
421
  color: var(--dark);
422
  position: relative;
@@ -598,133 +598,9 @@
598
 
599
  .job-header h3 {
600
  font-size: 1.5rem;
601
- margin-bottom: 0.5rem;
602
- }
603
-
604
- .job-info {
605
- display: flex;
606
- justify-content: space-between;
607
- font-size: 0.9rem;
608
- opacity: 0.9;
609
- }
610
-
611
- .job-body {
612
- padding: 1.5rem;
613
- flex-grow: 1;
614
- }
615
-
616
- .job-description {
617
- margin-bottom: 1.5rem;
618
- }
619
-
620
- .job-footer {
621
- padding: 1rem 1.5rem;
622
- background-color: rgba(0, 0, 0, 0.03);
623
- display: flex;
624
- justify-content: flex-end;
625
- }
626
-
627
- .form-group {
628
- margin-bottom: 1.5rem;
629
- }
630
-
631
- .form-group label {
632
- display: block;
633
- margin-bottom: 0.5rem;
634
- font-weight: 500;
635
- }
636
-
637
- .form-control {
638
- width: 100%;
639
- padding: 0.75rem;
640
- border: 1px solid #ddd;
641
- border-radius: 5px;
642
- font-size: 1rem;
643
- }
644
-
645
- .form-control:focus {
646
- border-color: var(--primary);
647
- outline: none;
648
- box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.2);
649
- }
650
-
651
- textarea.form-control {
652
- min-height: 150px;
653
- }
654
-
655
- .flash-messages {
656
- margin: 1rem 0;
657
- }
658
-
659
- .alert {
660
- padding: 1rem;
661
- border-radius: 5px;
662
- margin-bottom: 1rem;
663
- }
664
-
665
- .alert-success {
666
- background-color: rgba(46, 204, 113, 0.2);
667
- border: 1px solid var(--success);
668
- color: #27ae60;
669
- }
670
-
671
- .alert-danger {
672
- background-color: rgba(231, 76, 60, 0.2);
673
- border: 1px solid var(--danger);
674
- color: #c0392b;
675
- }
676
-
677
- /* Breadcrumbs */
678
- .breadcrumbs {
679
- display: flex;
680
- padding: 1rem 0;
681
- margin-bottom: 1rem;
682
- list-style: none;
683
- }
684
-
685
- .breadcrumbs li {
686
- display: flex;
687
- align-items: center;
688
  }
689
 
690
- .breadcrumbs li:not(:last-child)::after {
691
- content: '/';
692
- margin: 0 0.5rem;
693
- color: #aaa;
694
- }
695
-
696
- .breadcrumbs a {
697
- color: var(--primary);
698
- text-decoration: none;
699
- }
700
-
701
- .breadcrumbs a:hover {
702
- text-decoration: underline;
703
- }
704
-
705
- @media screen and (max-width: 768px) {
706
- .nav-container {
707
- flex-direction: row;
708
- justify-content: space-between;
709
- }
710
-
711
- .luna-avatar-container {
712
- width: 180px;
713
- height: 180px;
714
- }
715
-
716
- .hero h1 {
717
- font-size: 2rem;
718
- }
719
-
720
- .hero p {
721
- font-size: 1rem;
722
- }
723
-
724
- .job-grid {
725
- grid-template-columns: 1fr;
726
- }
727
- }
728
  </style>
729
  </head>
730
  <body>
@@ -755,6 +631,8 @@
755
  <a href="{{ url_for('auth.signup') }}" class="btn btn-primary">Sign Up</a>
756
  {% endif %}
757
  </div>
 
 
758
 
759
  </div>
760
  </header>
@@ -775,7 +653,7 @@
775
 
776
  {% block content %}{% endblock %}
777
  </div>
778
-
779
  #CHATBOT START
780
  <!-- Chatbot Toggle Button -->
781
  <!--
@@ -784,7 +662,7 @@
784
  centred on all screen sizes. Additional media queries adjust the
785
  button's position and padding for very small viewports.
786
  -->
787
- <div id="chatbot-toggle" onclick="toggleChatbot()">💬 Chat</div>
788
 
789
  <!-- Chatbox Popup -->
790
  <div id="chatbot-box">
@@ -795,32 +673,41 @@
795
 
796
  <style>
797
  #chatbot-toggle {
 
798
  position: fixed;
799
- bottom: 1rem;
800
  right: 1rem;
 
 
 
801
  background-color: #4caf50;
802
- color: white;
803
- padding: 0.75rem 1rem;
804
- border-radius: 30px;
805
  cursor: pointer;
806
  z-index: 1000;
807
  display: flex;
808
  align-items: center;
809
  justify-content: center;
810
- font-size: 1rem;
811
- line-height: 1;
812
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
813
  transition: background-color 0.2s ease;
814
  }
815
 
816
  #chatbot-toggle:hover {
817
- background-color: #43a047; /* slightly darker green on hover */
 
 
 
 
 
818
  }
819
 
820
  #chatbot-box {
821
  position: fixed;
822
- bottom: calc(1rem + 3.5rem); /* sit above the toggle on desktop */
823
- right: 1rem;
 
 
824
  /* Default dimensions for larger screens */
825
  width: 20rem;
826
  height: 25rem;
@@ -849,31 +736,29 @@
849
  }
850
 
851
  /* Responsive adjustments for small screens */
852
- @media (max-width: 600px) {
 
 
 
 
 
 
 
 
 
 
 
853
  #chatbot-box {
854
  width: 90vw;
855
  height: 60vh;
856
- bottom: calc(1rem + 3rem);
857
  right: 5vw;
 
 
858
  }
859
  #chat-messages {
860
  max-height: calc(60vh - 5.5rem);
861
  }
862
- #chatbot-toggle {
863
- bottom: 1rem;
864
- right: 1rem;
865
- padding: 0.65rem 0.9rem;
866
- font-size: 0.9rem;
867
- }
868
- }
869
-
870
- @media (max-width: 400px) {
871
- #chatbot-toggle {
872
- bottom: 0.75rem;
873
- right: 0.75rem;
874
- padding: 0.6rem 0.8rem;
875
- font-size: 0.85rem;
876
- }
877
  }
878
 
879
  #chat-input {
@@ -994,4 +879,4 @@
994
  }
995
  </style>
996
  </body>
997
- </html>
 
416
  }
417
 
418
  .feature-content h3 {
419
+ font-size : 1.5rem;
420
  margin-bottom: 1rem;
421
  color: var(--dark);
422
  position: relative;
 
598
 
599
  .job-header h3 {
600
  font-size: 1.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
  }
602
 
603
+ /* Additional content styling omitted for brevity */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
  </style>
605
  </head>
606
  <body>
 
631
  <a href="{{ url_for('auth.signup') }}" class="btn btn-primary">Sign Up</a>
632
  {% endif %}
633
  </div>
634
+ <!-- Mobile chat icon visible only on small screens -->
635
+ <div id="chatbot-nav" class="chat-nav-icon" onclick="toggleChatbot()">💬</div>
636
 
637
  </div>
638
  </header>
 
653
 
654
  {% block content %}{% endblock %}
655
  </div>
656
+
657
  #CHATBOT START
658
  <!-- Chatbot Toggle Button -->
659
  <!--
 
662
  centred on all screen sizes. Additional media queries adjust the
663
  button's position and padding for very small viewports.
664
  -->
665
+ <div id="chatbot-toggle" onclick="toggleChatbot()">💬</div>
666
 
667
  <!-- Chatbox Popup -->
668
  <div id="chatbot-box">
 
673
 
674
  <style>
675
  #chatbot-toggle {
676
+ /* Floating circular button on desktop. It is vertically centred along the right edge */
677
  position: fixed;
678
+ top: 50%;
679
  right: 1rem;
680
+ transform: translateY(-50%);
681
+ width: 3rem;
682
+ height: 3rem;
683
  background-color: #4caf50;
684
+ color: #ffffff;
685
+ border-radius: 50%;
 
686
  cursor: pointer;
687
  z-index: 1000;
688
  display: flex;
689
  align-items: center;
690
  justify-content: center;
691
+ font-size: 1.5rem;
 
692
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
693
  transition: background-color 0.2s ease;
694
  }
695
 
696
  #chatbot-toggle:hover {
697
+ background-color: #43a047;
698
+ }
699
+
700
+ /* Chat icon inside the navbar (hidden by default and shown on small screens via media query) */
701
+ #chatbot-nav {
702
+ display: none;
703
  }
704
 
705
  #chatbot-box {
706
  position: fixed;
707
+ /* Align the chat window vertically with the toggle on desktop */
708
+ top: 50%;
709
+ right: calc(1rem + 3rem + 1rem);
710
+ transform: translateY(-50%);
711
  /* Default dimensions for larger screens */
712
  width: 20rem;
713
  height: 25rem;
 
736
  }
737
 
738
  /* Responsive adjustments for small screens */
739
+ @media (max-width: 768px) {
740
+ /* Hide the floating button and reveal the navbar icon on mobile */
741
+ #chatbot-toggle {
742
+ display: none !important;
743
+ }
744
+ #chatbot-nav {
745
+ display: block;
746
+ font-size: 1.5rem;
747
+ color: var(--accent);
748
+ margin-left: 1rem;
749
+ cursor: pointer;
750
+ }
751
  #chatbot-box {
752
  width: 90vw;
753
  height: 60vh;
754
+ bottom: 1rem;
755
  right: 5vw;
756
+ top: auto;
757
+ transform: none;
758
  }
759
  #chat-messages {
760
  max-height: calc(60vh - 5.5rem);
761
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
762
  }
763
 
764
  #chat-input {
 
879
  }
880
  </style>
881
  </body>
882
+ </html>
backend/templates/my_applications.html CHANGED
@@ -14,6 +14,21 @@
14
  <li>My Applications</li>
15
  </ul>
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  <div class="application-list">
18
  {% if applications %}
19
  {% for application in applications %}
@@ -87,5 +102,32 @@
87
  justify-content: flex-end;
88
  gap: 0.5rem;
89
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  </style>
91
- {% endblock %}
 
14
  <li>My Applications</li>
15
  </ul>
16
 
17
+ <!-- Prominent interview tips moved from the apply page. This section is placed
18
+ near the top of the My Applications page so candidates see the
19
+ guidelines before initiating their AI interview. It is responsive
20
+ and uses colours consistent with the overall theme. -->
21
+ <div class="tips-section">
22
+ <h3>Important Interview Guidelines</h3>
23
+ <ul>
24
+ <li>The interview can be taken only once, so please be prepared.</li>
25
+ <li>Make sure you are in a quiet environment with a stable internet connection.</li>
26
+ <li>This is not a final job interview, but it helps the company shortlist the most relevant candidates.</li>
27
+ <li>The interview is customized based on your CV and the job requirements.</li>
28
+ <li>It takes 10 to 15 minutes and includes both general and skill‑based questions.</li>
29
+ </ul>
30
+ </div>
31
+
32
  <div class="application-list">
33
  {% if applications %}
34
  {% for application in applications %}
 
102
  justify-content: flex-end;
103
  gap: 0.5rem;
104
  }
105
+
106
+ /* Interview tips styling. Creates a highlighted panel with a coloured
107
+ border and responsive padding. */
108
+ .tips-section {
109
+ background-color: #f8f9fa;
110
+ border-left: 5px solid var(--primary);
111
+ padding: 2rem;
112
+ margin: 2rem 0;
113
+ border-radius: 8px;
114
+ }
115
+ .tips-section h3 {
116
+ margin-top: 0;
117
+ color: var(--primary);
118
+ margin-bottom: 1rem;
119
+ font-size: 1.5rem;
120
+ }
121
+ .tips-section ul {
122
+ margin-left: 1rem;
123
+ padding-left: 1rem;
124
+ list-style-type: disc;
125
+ line-height: 1.6;
126
+ }
127
+ @media (max-width: 600px) {
128
+ .tips-section {
129
+ padding: 1rem;
130
+ }
131
+ }
132
  </style>
133
+ {% endblock %}