Spaces:
Running
Running
Nikolay Angelov
commited on
Commit
·
3b3fbd6
1
Parent(s):
50ba800
add google analytics
Browse files- README.md +1 -1
- app.py +1 -0
- frontend/public/index.html +24 -2
- frontend/src/components/ChatFooter.tsx +20 -2
- frontend/src/components/PDPDialog.tsx +26 -11
README.md
CHANGED
@@ -6,7 +6,7 @@ colorTo: indigo
|
|
6 |
sdk: docker
|
7 |
app_port: 8000
|
8 |
python_version: 3.12.3
|
9 |
-
short_description: "AI career coach powered by Llama-3.3-70B"
|
10 |
tags:
|
11 |
- career
|
12 |
- ai
|
|
|
6 |
sdk: docker
|
7 |
app_port: 8000
|
8 |
python_version: 3.12.3
|
9 |
+
short_description: "AI career coach powered by Llama-3.3-70B-Instruct"
|
10 |
tags:
|
11 |
- career
|
12 |
- ai
|
app.py
CHANGED
@@ -48,6 +48,7 @@ app.add_middleware(
|
|
48 |
if not os.getenv('HUGGINGFACEHUB_API_TOKEN'):
|
49 |
raise ValueError("Please set HUGGINGFACEHUB_API_TOKEN environment variable")
|
50 |
|
|
|
51 |
model = "meta-llama/Llama-3.3-70B-Instruct"
|
52 |
|
53 |
# Initialize the HuggingFace pipeline with more strict parameters
|
|
|
48 |
if not os.getenv('HUGGINGFACEHUB_API_TOKEN'):
|
49 |
raise ValueError("Please set HUGGINGFACEHUB_API_TOKEN environment variable")
|
50 |
|
51 |
+
#model = "nvidia/Llama-3.1-Nemotron-70B-Instruct-HF"
|
52 |
model = "meta-llama/Llama-3.3-70B-Instruct"
|
53 |
|
54 |
# Initialize the HuggingFace pipeline with more strict parameters
|
frontend/public/index.html
CHANGED
@@ -2,17 +2,39 @@
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="utf-8" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
<meta name="theme-color" content="#000000" />
|
8 |
<meta
|
9 |
name="description"
|
10 |
-
content="AI CareerCoach - Your personal career development assistant"
|
11 |
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
13 |
-
<title>AI CareerCoach</title>
|
|
|
|
|
14 |
</head>
|
15 |
<body>
|
|
|
16 |
<noscript>You need to enable JavaScript to run this app.</noscript>
|
17 |
<div id="root"></div>
|
18 |
</body>
|
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="utf-8" />
|
5 |
+
|
6 |
+
<!-- Google tag (gtag.js) -->
|
7 |
+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-MMXJ7F6PTQ"></script>
|
8 |
+
<script>
|
9 |
+
window.dataLayer = window.dataLayer || [];
|
10 |
+
function gtag(){dataLayer.push(arguments);}
|
11 |
+
gtag('js', new Date());
|
12 |
+
|
13 |
+
gtag('config', 'G-MMXJ7F6PTQ');
|
14 |
+
</script>
|
15 |
+
|
16 |
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
17 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
18 |
<meta name="theme-color" content="#000000" />
|
19 |
<meta
|
20 |
name="description"
|
21 |
+
content="AI CareerCoach - Your personal career development assistant powered by artificial intelligence. Get personalized career guidance, job search assistance, and professional development advice."
|
22 |
/>
|
23 |
+
<meta name="keywords" content="AI career coach, career development, job search, professional guidance, career advice, AI assistant" />
|
24 |
+
<meta name="author" content="AI CareerCoach" />
|
25 |
+
<meta name="robots" content="index, follow" />
|
26 |
+
<meta property="og:title" content="AI CareerCoach - Your Personal Career Development Assistant" />
|
27 |
+
<meta property="og:description" content="Get personalized career guidance and professional development advice powered by AI." />
|
28 |
+
<meta property="og:type" content="website" />
|
29 |
+
<meta property="og:url" content="%PUBLIC_URL%" />
|
30 |
+
<meta name="twitter:card" content="summary_large_image" />
|
31 |
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
32 |
+
<title>AI CareerCoach - Your Personal Career Development Assistant</title>
|
33 |
+
|
34 |
+
|
35 |
</head>
|
36 |
<body>
|
37 |
+
|
38 |
<noscript>You need to enable JavaScript to run this app.</noscript>
|
39 |
<div id="root"></div>
|
40 |
</body>
|
frontend/src/components/ChatFooter.tsx
CHANGED
@@ -1,6 +1,13 @@
|
|
1 |
import React from 'react';
|
2 |
import styled from 'styled-components';
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
const FooterContainer = styled.div`
|
5 |
display: flex;
|
6 |
justify-content: space-around;
|
@@ -41,16 +48,27 @@ interface ChatFooterProps {
|
|
41 |
}
|
42 |
|
43 |
const ChatFooter: React.FC<ChatFooterProps> = ({ onOpenFeedback, onOpenPDP }) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
return (
|
45 |
<FooterContainer>
|
46 |
<FeedbackButton onClick={onOpenFeedback}>
|
47 |
Send Feedback
|
48 |
</FeedbackButton>
|
49 |
-
<PDPButton onClick={
|
50 |
Generate Personal Development Plan
|
51 |
</PDPButton>
|
52 |
</FooterContainer>
|
53 |
);
|
54 |
};
|
55 |
|
56 |
-
export default ChatFooter;
|
|
|
1 |
import React from 'react';
|
2 |
import styled from 'styled-components';
|
3 |
|
4 |
+
// Declare gtag on the Window object to resolve TypeScript error
|
5 |
+
declare global {
|
6 |
+
interface Window {
|
7 |
+
gtag?: (...args: any[]) => void;
|
8 |
+
}
|
9 |
+
}
|
10 |
+
|
11 |
const FooterContainer = styled.div`
|
12 |
display: flex;
|
13 |
justify-content: space-around;
|
|
|
48 |
}
|
49 |
|
50 |
const ChatFooter: React.FC<ChatFooterProps> = ({ onOpenFeedback, onOpenPDP }) => {
|
51 |
+
const handlePDPButtonClick = () => {
|
52 |
+
if (window.gtag) {
|
53 |
+
window.gtag('event', 'click', {
|
54 |
+
event_category: 'ChatFooter',
|
55 |
+
event_label: 'PDPButton',
|
56 |
+
value: 1,
|
57 |
+
});
|
58 |
+
}
|
59 |
+
onOpenPDP();
|
60 |
+
};
|
61 |
+
|
62 |
return (
|
63 |
<FooterContainer>
|
64 |
<FeedbackButton onClick={onOpenFeedback}>
|
65 |
Send Feedback
|
66 |
</FeedbackButton>
|
67 |
+
<PDPButton onClick={handlePDPButtonClick}>
|
68 |
Generate Personal Development Plan
|
69 |
</PDPButton>
|
70 |
</FooterContainer>
|
71 |
);
|
72 |
};
|
73 |
|
74 |
+
export default ChatFooter;
|
frontend/src/components/PDPDialog.tsx
CHANGED
@@ -1,6 +1,13 @@
|
|
1 |
-
import React, { useState } from 'react';
|
2 |
import styled from 'styled-components';
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
const DialogOverlay = styled.div`
|
5 |
position: fixed;
|
6 |
top: 0;
|
@@ -176,7 +183,7 @@ export interface PDPFormData {
|
|
176 |
targetDate: string;
|
177 |
}
|
178 |
|
179 |
-
const PDPDialog:
|
180 |
const [formData, setFormData] = useState<PDPFormData>({
|
181 |
cvFile: null,
|
182 |
careerGoal: '',
|
@@ -188,28 +195,28 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
188 |
|
189 |
if (!isOpen) return null;
|
190 |
|
191 |
-
const handleFileChange = (event:
|
192 |
const file = event.target.files?.[0];
|
193 |
if (file && file.type === 'application/pdf') {
|
194 |
-
setFormData(prev => ({ ...prev, cvFile: file }));
|
195 |
} else {
|
196 |
alert('Please select a PDF file');
|
197 |
}
|
198 |
};
|
199 |
|
200 |
-
const handleDrop = (event:
|
201 |
event.preventDefault();
|
202 |
setDragOver(false);
|
203 |
|
204 |
const file = event.dataTransfer.files[0];
|
205 |
if (file && file.type === 'application/pdf') {
|
206 |
-
setFormData(prev => ({ ...prev, cvFile: file }));
|
207 |
} else {
|
208 |
alert('Please select a PDF file');
|
209 |
}
|
210 |
};
|
211 |
|
212 |
-
const handleDragOver = (event:
|
213 |
event.preventDefault();
|
214 |
setDragOver(true);
|
215 |
};
|
@@ -224,6 +231,14 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
224 |
return;
|
225 |
}
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
onSubmit(formData);
|
228 |
onClose();
|
229 |
|
@@ -236,7 +251,7 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
236 |
});
|
237 |
};
|
238 |
|
239 |
-
const handleOverlayClick = (event:
|
240 |
if (event.target === event.currentTarget) {
|
241 |
onClose();
|
242 |
}
|
@@ -277,7 +292,7 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
277 |
<TextArea
|
278 |
placeholder="Describe your career aspirations and goals..."
|
279 |
value={formData.careerGoal}
|
280 |
-
onChange={(e) => setFormData(prev => ({ ...prev, careerGoal: e.target.value }))}
|
281 |
/>
|
282 |
</FormGroup>
|
283 |
|
@@ -286,7 +301,7 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
286 |
<TextArea
|
287 |
placeholder="Any specific skills, industries, or preferences you'd like to mention..."
|
288 |
value={formData.additionalContext}
|
289 |
-
onChange={(e) => setFormData(prev => ({ ...prev, additionalContext: e.target.value }))}
|
290 |
/>
|
291 |
</FormGroup>
|
292 |
|
@@ -295,7 +310,7 @@ const PDPDialog: React.FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
|
295 |
<DateInput
|
296 |
type="date"
|
297 |
value={formData.targetDate}
|
298 |
-
onChange={(e) => setFormData(prev => ({ ...prev, targetDate: e.target.value }))}
|
299 |
min={new Date().toISOString().split('T')[0]}
|
300 |
/>
|
301 |
</FormGroup>
|
|
|
1 |
+
import React, { useState, FC, ChangeEvent, DragEvent, MouseEvent } from 'react';
|
2 |
import styled from 'styled-components';
|
3 |
|
4 |
+
// Declare gtag on the Window object to resolve TypeScript error
|
5 |
+
declare global {
|
6 |
+
interface Window {
|
7 |
+
gtag?: (...args: any[]) => void;
|
8 |
+
}
|
9 |
+
}
|
10 |
+
|
11 |
const DialogOverlay = styled.div`
|
12 |
position: fixed;
|
13 |
top: 0;
|
|
|
183 |
targetDate: string;
|
184 |
}
|
185 |
|
186 |
+
const PDPDialog: FC<PDPDialogProps> = ({ isOpen, onClose, onSubmit }) => {
|
187 |
const [formData, setFormData] = useState<PDPFormData>({
|
188 |
cvFile: null,
|
189 |
careerGoal: '',
|
|
|
195 |
|
196 |
if (!isOpen) return null;
|
197 |
|
198 |
+
const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
|
199 |
const file = event.target.files?.[0];
|
200 |
if (file && file.type === 'application/pdf') {
|
201 |
+
setFormData((prev: PDPFormData) => ({ ...prev, cvFile: file }));
|
202 |
} else {
|
203 |
alert('Please select a PDF file');
|
204 |
}
|
205 |
};
|
206 |
|
207 |
+
const handleDrop = (event: DragEvent) => {
|
208 |
event.preventDefault();
|
209 |
setDragOver(false);
|
210 |
|
211 |
const file = event.dataTransfer.files[0];
|
212 |
if (file && file.type === 'application/pdf') {
|
213 |
+
setFormData((prev: PDPFormData) => ({ ...prev, cvFile: file }));
|
214 |
} else {
|
215 |
alert('Please select a PDF file');
|
216 |
}
|
217 |
};
|
218 |
|
219 |
+
const handleDragOver = (event: DragEvent) => {
|
220 |
event.preventDefault();
|
221 |
setDragOver(true);
|
222 |
};
|
|
|
231 |
return;
|
232 |
}
|
233 |
|
234 |
+
// Track Generate PDP button click
|
235 |
+
if (window.gtag) {
|
236 |
+
window.gtag('event', 'click', {
|
237 |
+
'event_category': 'Button',
|
238 |
+
'event_label': 'Generate PDP Button - Dialog',
|
239 |
+
});
|
240 |
+
}
|
241 |
+
|
242 |
onSubmit(formData);
|
243 |
onClose();
|
244 |
|
|
|
251 |
});
|
252 |
};
|
253 |
|
254 |
+
const handleOverlayClick = (event: MouseEvent) => {
|
255 |
if (event.target === event.currentTarget) {
|
256 |
onClose();
|
257 |
}
|
|
|
292 |
<TextArea
|
293 |
placeholder="Describe your career aspirations and goals..."
|
294 |
value={formData.careerGoal}
|
295 |
+
onChange={(e) => setFormData((prev: PDPFormData) => ({ ...prev, careerGoal: e.target.value }))}
|
296 |
/>
|
297 |
</FormGroup>
|
298 |
|
|
|
301 |
<TextArea
|
302 |
placeholder="Any specific skills, industries, or preferences you'd like to mention..."
|
303 |
value={formData.additionalContext}
|
304 |
+
onChange={(e) => setFormData((prev: PDPFormData) => ({ ...prev, additionalContext: e.target.value }))}
|
305 |
/>
|
306 |
</FormGroup>
|
307 |
|
|
|
310 |
<DateInput
|
311 |
type="date"
|
312 |
value={formData.targetDate}
|
313 |
+
onChange={(e) => setFormData((prev: PDPFormData) => ({ ...prev, targetDate: e.target.value }))}
|
314 |
min={new Date().toISOString().split('T')[0]}
|
315 |
/>
|
316 |
</FormGroup>
|