From 854bc3fb41d510666bd2c527fc65689ba22b6231 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 3 Dec 2025 17:23:10 +0000 Subject: [PATCH] 1 --- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 368 bytes core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 1319 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 3410 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 569 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 3308 bytes core/admin.py | 3 +- core/forms.py | 16 ++ core/migrations/0001_initial.py | 38 +++ core/migrations/0002_studentprofile.py | 32 +++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 2078 bytes .../0002_studentprofile.cpython-311.pyc | Bin 0 -> 2084 bytes core/models.py | 43 +++- core/templates/base.html | 24 ++ core/templates/core/career_explorer.html | 80 +++++++ core/templates/core/index.html | 223 +++++++----------- core/templates/core/student_profile_form.html | 34 +++ core/urls.py | 5 +- core/views.py | 41 ++++ static/css/custom.css | 55 ++++- static/images/icon-achieve.svg | 3 + static/images/icon-assess.svg | 3 + static/images/icon-plan.svg | 3 + staticfiles/css/custom.css | 64 +++-- staticfiles/images/icon-achieve.svg | 3 + staticfiles/images/icon-assess.svg | 3 + staticfiles/images/icon-plan.svg | 3 + 26 files changed, 513 insertions(+), 163 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/0002_studentprofile.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0002_studentprofile.cpython-311.pyc create mode 100644 core/templates/core/career_explorer.html create mode 100644 core/templates/core/student_profile_form.html create mode 100644 static/images/icon-achieve.svg create mode 100644 static/images/icon-assess.svg create mode 100644 static/images/icon-plan.svg create mode 100644 staticfiles/images/icon-achieve.svg create mode 100644 staticfiles/images/icon-assess.svg create mode 100644 staticfiles/images/icon-plan.svg diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855b12f4883b1ba9de01c54245c53aacd714..af32b26db9a1be42b218491c7d9b26c7b888dd73 100644 GIT binary patch delta 274 zcmcb@_<^Z@IWI340}yN}G|0>Z(vLwL7+{7nJ_i9A(-~42QW$d>av7r-85vTTQkZj? za+#x;85vR;vshqS7O=ut$aE_6GDZf5)j$jZK>aMi44SMj)j@ns##^k3DY=<>FF^`` zJig$P(v;M^l7OQ8w9K4TKTWoY{-UzC*mCnzQge!nKvvvhDb6fOy~RuImiKml%X6_+4aBzQUk<0fvgWff@m87dqnr delta 156 zcmeysbcHcxIWI340}y=Q^((_3NIwQ~V1NnA_$&luOlL@8NMX!j$YqRTWMoKT3TDt` zehE^b$#{!3F(o%M&rg%-7GFwMVqSW_UUGh3Nl|7}5i?N1#2b$K96*{8h>K-`#0O?Z QM#dWq3Ky`UA~v8305E7Gc>n+a diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99018bfa7d9439655710af797a4e825b7d7e67e7 GIT binary patch literal 1319 zcmd5*%}*0S6rb6zwtOh5p->YkX*ALUlp6^W1Hs_IKr|Q+d)cfz)4FuKTV{3zV`4mb z;OM~w4jhactieMQFC6_7+N6hOub#LqDJM?8>4KzzKft#;zq~i|=Dpv{d-HvGcmRP+ zZ_e7kB!vD5<3iMPrTYk!T|^MU4ys}uV?-n(J5p8FWsD^B7!l^ppZG&6Z6wb9dPlbLPvrne z9}40<`QLnqy07ZV__EK&uHM1SD)r4mDojxlSf+1#ZkV!NpEAmQ9^N!-zAb8DaLa?K zP~#Qbad?;lBdAitCgCu#%eLcL70QH}a!j`zm}PJtwLF(Y84W0|QS+Ez@*LX>)0W97 zIM*00K_1rvSA}_7{8+SyXa>{w884`85NtLiU|7J2fHc4w5KbC~YXSo!959TkM*>Ia zLx!;#m`=RHM8k$EEK(=bN;Y)}XCg zceE&pZcpuv?oZTTH#X~)W_G@noo{F7JGtq-VE+xg{aP`fn{A%LBP_}B#S zWRn1E1%+jVF(zPKz@&gX0(xFKp^2vNfp~p<0pRkKku<16@T+hl=1#9!hy#n5YXvRT z$Od$b7Z*nB6^qA}ORb8^iI*A^=qGiST!_p5kllq);stU8Ad)f09W>tT|2rt(?EfQW U2m|q}0QZ_Z5%Z_lEcVF%1^tsmod5s; literal 0 HcmV?d00001 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 9aa598b9d5171b2bb0d207f045e07f9fbbb95a64..02069c8e79d70bbb145618fcbe4be2b2c99f5237 100644 GIT binary patch literal 3410 zcmcImO>Emn7A7U?U$PWQR;)&ig~Tl?w6ToT5Tc|=(sk-|^J5#ZTkHx85VSb9=}@FH zB-=PB3LSdzp$8ob#6Y(|4vVaVa7*BkK6&oD3G@0FV0)#5-aaEcZOc7t-D5v&DSoFgQM8sS(BTGjLaq+D(qei9y&-$O$YykYxGy z|ANt_=RPOe5FYU|QC9UeCuk_rLxVtTU|ANF2M(tgvRr3-D}XnCZ&mt0YYKHzuB()k zJr7SdH=Gd9YdYom#|d|}ll#>O7}GG)T1+>Y`EkPxkL}^)bEUWw=6Rf$=bb3egC#@8 z?>NstGz8h}p}2AHe$IB`m3K_?==t}bgd1D2jMGz%}9MuAc93Y=4GfoS!A-PpO!iXA)mRO?Ke zu`5>WiXFSsy46izXn$y@FKlN!x6E|aN>}Z4wRN|fFKy-Qe5u3jOq=sQ&C2CJ{04GB^elmk8eV!1`z4Tjtdn(Mf_590F8rqcfipRPzQSfUD9Pj5tAO^ycoow ze4IX5R}V%x)H{IDV>6t0gJZ6grlZhDQGuRCfzeCHP<((QkK#QLPV&B>Y%HlLJuG1y zIY~+$8WIImXvi`eJ%_CceWNMW1(~O+Of)B4mkmuP6fmR-vOqU@Dk!VONvu-!TYZh! zDN#htIim@UCV-f#g4ht6yd=6PqvvrA2S6)g6$QFZdkx|c(Bg&7Svy|X_5-5gRV!Y# zr3fjlU@%@<*(aP%XqMCT2SP~3!x8?sQxHx9kVpEcc*zc6 z^ms1vi+;#h5Fdw9HD;rzh&_RU@v#$o5ZS}Wcz8aX+lI~Q;rah*A)<%Rl7b%p`Wf)1 zTf`tR2Kea(CN8(s(kG71xD1fpXMmAK-4KbQFJQ8e2^>yDRd_fQ0>SQ4!bPy?Qo=0s zhD5R=7_xo@?|4N((CrmLz-@^=oMPAei~5=Q#Rs(Gn|mDJpRTx~(qhTya2O0u7$vgH za8k$}U22aQK886pWB|;sm$$@!O7{6FGkF=G@a27u7#+qDPGVjmODYI2V{%{NDnc`# zFV1{^>kIlR*mP;ci4f7K3z%R%Ziq+TD=v*5uid{d?RiYiO0lkO2QB`Ywi zQYT*O9we1At{25P{52oA{Sc|d#xZ-3Kjk{XUq{T?4J&rTj@^L#ohr72cB;5N)6ri| zn5o-V>b9M_-TG@cm2XF$a@*5pYRXDY*{LaL%Z;}smpgJ5D_5~|6=0e~Zu9S3OWT~8 zxMU?R*@;W7*^`a#(^AL3GyMvP>8_Q%YiI8QF%6roP~Mug3+0`FS-5T$uG@v{CYSH# zFKp%A+eW@><*RnS3fBsxollW=28BmE=#;rq%!!EW;CgjZT=s5Nf%`~5-nFL)I!91!}ufonRlJLPG>;{A)s|Z?D|=j?J@=P z=(Ed(Sh)Wj7n`#`-g|@XZx1@tF&5bMxM=5oD!jq=w+EdChAo@S)xcIa%2+vO50c=5PsfBn-x-eCLNA)T(D{|EV-C;I>Z literal 209 zcmZ3^%ge<81S>LrWmp2~#~=<2FhLogg@BCd3@HpLj5!Rsj8Tk?3@J>(44TX@K?*b( zZ?Wa(r=;c-`)M-W;!Md(%uCPLOGzqX21>4E_zY6>OHV%|KQ~psG^sSNq*On(A~m_R zB)>?%JijQrxF9h(RX;huC{-U~j9x+IFAf_ZyEG@&u80Guoe_wOWr4&8W=2NF8w@fR Ku%RM0pb7xTsWln^ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 1f807fae1897c89361c99c5e868a26d00799b73f..b35138a3ccbe7cd47baf3a12c4ce1b74083612cf 100644 GIT binary patch literal 569 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 delta 199 zcmaDOd4-E_IWI340}$*?|CM3GJdsa=(P5&xHCGEm6lV%!FoP!B#1q<^c^Q{83Ge|` z-Qp<7Ni0drFUl?ApL~Q_fm;wLSi}n=#3sLI_FUx@turr7IbVTZlX-=wLkus3W2*kx{lV5QM$bDcF NU^M^0fJuNg0|3*$E_eU{ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..6364bf1 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,4 @@ from django.contrib import admin +from .models import StudentProfile -# Register your models here. +admin.site.register(StudentProfile) diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..61c719d --- /dev/null +++ b/core/forms.py @@ -0,0 +1,16 @@ +from django import forms +from .models import StudentProfile + +class StudentProfileForm(forms.ModelForm): + class Meta: + model = StudentProfile + fields = ['education', 'interests', 'aptitude_scores', 'skills', + 'resume_id', 'digilocker_id', 'languages', + 'consent_for_portfolio', 'career_preferences'] + widgets = { + 'interests': forms.Textarea(attrs={'rows': 3}), + 'aptitude_scores': forms.Textarea(attrs={'rows': 3}), + 'skills': forms.Textarea(attrs={'rows': 3}), + 'languages': forms.Textarea(attrs={'rows': 3}), + 'career_preferences': forms.Textarea(attrs={'rows': 3}), + } \ No newline at end of file diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..5cfbcdb --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# Generated by Django 5.2.7 on 2025-12-03 17:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Skill', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True)), + ('description', models.TextField(blank=True, null=True)), + ('proficiency_levels', models.JSONField(blank=True, null=True)), + ('related_jobs', models.JSONField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='CareerPath', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255, unique=True)), + ('description', models.TextField(blank=True, null=True)), + ('typical_roles', models.JSONField(blank=True, null=True)), + ('clusters', models.JSONField(blank=True, null=True)), + ('salary_range', models.CharField(blank=True, max_length=255, null=True)), + ('growth_trends', models.TextField(blank=True, null=True)), + ('sample_roadmap_id', models.CharField(blank=True, max_length=255, null=True)), + ('required_skills', models.ManyToManyField(related_name='career_paths', to='core.skill')), + ], + ), + ] diff --git a/core/migrations/0002_studentprofile.py b/core/migrations/0002_studentprofile.py new file mode 100644 index 0000000..d48248b --- /dev/null +++ b/core/migrations/0002_studentprofile.py @@ -0,0 +1,32 @@ +# Generated by Django 5.2.7 on 2025-12-03 17:20 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='StudentProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('education', models.CharField(blank=True, max_length=255, null=True)), + ('interests', models.JSONField(blank=True, null=True)), + ('aptitude_scores', models.JSONField(blank=True, null=True)), + ('skills', models.JSONField(blank=True, null=True)), + ('resume_id', models.CharField(blank=True, max_length=255, null=True)), + ('digilocker_id', models.CharField(blank=True, max_length=255, null=True)), + ('languages', models.JSONField(blank=True, null=True)), + ('consent_for_portfolio', models.BooleanField(default=False)), + ('career_preferences', models.JSONField(blank=True, null=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62ce9b5dc04ab2122f61ec52a826b8b371ba595b GIT binary patch literal 2078 zcmb_cO-vg{6rNrGU>h6O;9yKjVk6hoNWmtp5-EyWwYV5iaVmjQ>XxpSoxxsMd(G^c zKn@j$9(v5J963={;lR;HjvU9*9<0eFQct-#f>SQ-%-WC=+LTJ2-F^FJ=9~AvdGqG| z8VUsfYcFb9ZP^RJ@4R!~JYD7VAya+<5I{i(6`?3p#G)tw5##|Be*(~jgmu^Xq64Nq zzvvZR(7g!Ko>zQ2Ez&?mD`CabjH*e!6$2vORL@uPf4JK@{ZZsD5hw}}6h$Z$T_sR- zivW4n8O=_EB6P8lo^{{FhyVrXhMq(3ft%4_U#G2!u*X6A&qtsS3Wxp!=H)s2E>Hmn z<%EQfF>AtM?-f+gLG^Z*{Szv59aPD4*mv1JTlLpH_Wy@HN{+|>XOH3Qu!jTJLJhvd zOK_qextuEOjBYr%e~bRmHLXP*T=3$QhGFb*C*$I*?(||0q;!tM} zWEzy^&AOs~szo1limJBXC0|BFky5;IOaLO!#H=kw7Mg?W+tM#f?&!BCj zGW$65#K0S7O;J&X?=$nZ%w@9K?3CPPJz3kqynH!=D`r~&VE5vA**CD8Z@YzvclWEd z5BP8Y9I$=2TH)cB;Tt46@odYEPBh#nNm7(a6_cphjGA`TB$Cw%M@cNbH)O}sM~lZ1 z5}RqpX6)Duk@BtZEfUY}d+m7k$U07vc)l6W+wnY+W?SJ8$@u;KEqnZa1D-_4c%eC7 zu*VBTdejQvCW)#2Av-bEa36m{60^<3teu!8(p(bK$~7!9nrn{c?9m*NzPz-NlR>ih4M{9F6U%mDnMmKZ!tb$}B&mD*Yj)~hW9dXC z%iojKN;9=$r&fscLn}N+k`MN0?Bs)!KJs0OB+JcY*-n;;q_qbFJU}5HASTYZXh&lM z-rafr;Ouz{6j&MY!*zD$j7hlaWU-UDog~R{n1h{S+8f`)&Yk!af6TfpZ-DujiMC4+ igtiw5X#zgF`nJ7s!P^E`#j}7dC13N2v%i^j{Qe10TQa}^ literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0002_studentprofile.cpython-311.pyc b/core/migrations/__pycache__/0002_studentprofile.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ac3fdbca367e6ffe5009f9eb5badbf903017811 GIT binary patch literal 2084 zcma)7J#Z686uvv1&N^APB_ks=&M4q02#LXR7y`^BFtLpt0{$VfoQYL%bJniJ*{3_P zcW2{N6e&`YDoiRWhYT(#T~JU`u4cB-Y?YZ*bYh^QN#5OA3I+=A>Gs~+{odR6-oE$r z=g?4GfN|sQl<`|s5dQI*-T*!ruW!NUcL51VG=-`NU&)l3k!nQr*CM9ej8>yfrK*U6 zBz!9%`4<62adczgKwj952*MM1!%-bT;)+mIUi$1(QRFcPyRKn1oT9|zO`}0{*RU;z zD@_|=)2SWE1)tFa=Ji#{w+RRKR3#)z0*-9RJt&;6^ypm?PKP%f4XHX1U}L=%B%uhb zs2f2f{8c2w6Gh72z%FQf($`v-P%J?H@A&&MZVc{a4zD%D>M?WzGBC^4#a^~S>d7^mV4j$on)*UBEWSJ; zi`aF;#9T5^Wu8mlT`S5wp?j{a)d<#IjQC)S7)_n*Xq$M4s}3e0Zu|`TwlG<@9jsY; z6LS?KuNI{D%YVU>VuVN6P2Jjryw~q(Cbk;x9WGm*X>!%DTuiXzLRpYw048HF@e#e{ z8op7Q2MVouZcAS@gZb14AZV{V&bzZoY3&}27t$EP*~uPR=0`PvWZ)_ zO~Zy796-3Pd#1}rYdXOo*CMzM$6Ga!l0EPTBBa`u1{H~22!w0IOEEvs6s; zm=^e{X*{lJP`;jtflg@JT~9ZCu%;2eoOs&V)>|!o9rh7!VGDv>+aZ3B;3LzkmFwE- z%G?jy;_|h*1)k_53@~PJHi-D5-y4YEqIhD)XiURh%=>0=b@q-<4#*oT%S$1dn6YgW z>sH7OEnB!^!xXX#+JFezTte$S7B~p~hY!q7ugp$go8xi2g%5htU&3oRQFuFFzGF9W z*<1H4*DK?DxCZBw^0rMjot9q1W&du<|M#*oWYu}i36rT6CevhVhxjcrnEY1ocyYFV{((`a3m7Go=SxEK}N- zU*u_3qZXkVr=4+F#-T~Kllp|_CLh*WZt`j6d5zwx(A;V}x5{#>H2LG7W6sdhmB*)9>B@6VOAGDN z0xK=h;G{%E==8s tD2k91;wdVe41b*-@y^N_DtzSERZfUXSNL#x5NFB!D}Uq7M|K0N{sVzHIr{(r literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..c0fa65d 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,44 @@ from django.db import models -# Create your models here. +class Skill(models.Model): + name = models.CharField(max_length=255, unique=True) + description = models.TextField(blank=True, null=True) + proficiency_levels = models.JSONField(blank=True, null=True) # e.g., ["Beginner", "Intermediate", "Advanced"] + related_jobs = models.JSONField(blank=True, null=True) # e.g., ["Software Engineer", "Data Scientist"] + + def __str__(self): + return self.name + +class CareerPath(models.Model): + title = models.CharField(max_length=255, unique=True) + description = models.TextField(blank=True, null=True) + required_skills = models.ManyToManyField(Skill, related_name='career_paths') # Many-to-Many relationship with Skill + typical_roles = models.JSONField(blank=True, null=True) # e.g., ["Junior Developer", "Senior Developer"] + clusters = models.JSONField(blank=True, null=True) # e.g., ["Software Development", "AI/ML"] + salary_range = models.CharField(max_length=255, blank=True, null=True) # e.g., "$50k - $80k" + growth_trends = models.TextField(blank=True, null=True) + sample_roadmap_id = models.CharField(max_length=255, blank=True, null=True) # Reference to a roadmap + + def __str__(self): + return self.title + + +from django.contrib.auth import get_user_model +from django.db.models import JSONField # Import JSONField + +User = get_user_model() + +class StudentProfile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + education = models.CharField(max_length=255, blank=True, null=True) + interests = JSONField(blank=True, null=True) + aptitude_scores = JSONField(blank=True, null=True) + skills = JSONField(blank=True, null=True) + resume_id = models.CharField(max_length=255, blank=True, null=True) + digilocker_id = models.CharField(max_length=255, blank=True, null=True) + languages = JSONField(blank=True, null=True) + consent_for_portfolio = models.BooleanField(default=False) + career_preferences = JSONField(blank=True, null=True) + + def __str__(self): + return f"Profile for {self.user.username}" diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..b5e5326 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -3,7 +3,9 @@ + {% block title %}Knowledge Base{% endblock %} + {% if project_description %} @@ -19,6 +21,28 @@ + {% block content %}{% endblock %} diff --git a/core/templates/core/career_explorer.html b/core/templates/core/career_explorer.html new file mode 100644 index 0000000..bcbb939 --- /dev/null +++ b/core/templates/core/career_explorer.html @@ -0,0 +1,80 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}Career Explorer - AI Career Advisor{% endblock %} + +{% block content %} +
+
+

Explore Career Paths

+

Discover various career opportunities and the skills required to achieve them.

+
+
+ +
+
+

Available Career Paths

+
+ {% for career_path in career_paths %} +
+
+
+
{{ career_path.title }}
+

{{ career_path.description }}

+
Required Skills:
+
    + {% for skill in career_path.required_skills.all %} +
  • {{ skill.name }}
  • + {% endfor %} +
+ {% if career_path.typical_roles %} +
Typical Roles:
+
    + {% for role in career_path.typical_roles %} +
  • {{ role }}
  • + {% endfor %} +
+ {% endif %} + {% if career_path.salary_range %} +

Salary Range: {{ career_path.salary_range }}

+ {% endif %} +
+
+
+ {% empty %} +
+

No career paths available yet.

+
+ {% endfor %} +
+
+ +
+

Skills Catalog

+
+ {% for skill in skills %} +
+
+
+
{{ skill.name }}
+

{{ skill.description }}

+ {% if skill.proficiency_levels %} +
Proficiency Levels:
+
    + {% for level in skill.proficiency_levels %} +
  • {{ level }}
  • + {% endfor %} +
+ {% endif %} +
+
+
+ {% empty %} +
+

No skills available yet.

+
+ {% endfor %} +
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..32e2d86 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,88 @@ -{% extends "base.html" %} +{% extends 'base.html' %} +{% load static %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}AI Career Advisor{% endblock %} {% block content %}
-
-

Analyzing your requirements and generating your app…

-
- Loading… -
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
+
+
+

Unlock Your Potential with AI Career Advisor

+

Get personalized career path recommendations, skill development roadmaps, and job matching powered by advanced AI.

+ Start Your Assessment +
+
+ +
+
+

How It Works

+
+
+
+ Assess Icon +

1. Assess Your Skills

+

Take our AI-powered assessments to identify your strengths, interests, and potential career aptitudes.

+
+
+
+
+ Plan Icon +

2. Plan Your Path

+

Receive a personalized career roadmap with recommended courses, projects, and learning resources.

+
+
+
+
+ Achieve Icon +

3. Achieve Your Goals

+

Track your progress, earn certifications, and get matched with relevant job and internship opportunities.

+
+
+
+
+
+ +
+
+

Success Stories

+
+
+
+

"The AI Career Advisor helped me discover my true calling and provided a clear path to achieve my dreams. I'm now pursuing a career I'm passionate about!"

+
Priya S., Successful Software Engineer
+
+
+
+
+
+ +
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/core/templates/core/student_profile_form.html b/core/templates/core/student_profile_form.html new file mode 100644 index 0000000..f737bf3 --- /dev/null +++ b/core/templates/core/student_profile_form.html @@ -0,0 +1,34 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+
+
+

+ {% if student_profile %}Edit Your Profile{% else %}Create Your Profile{% endif %} +

+
+ {% csrf_token %} + {% for field in form %} +
+ + {{ field }} + {% if field.help_text %} +
{{ field.help_text }}
+ {% endif %} + {% if field.errors %} + {% for error in field.errors %} +
{{ error }}
+ {% endfor %} + {% endif %} +
+ {% endfor %} + +
+
+
+
+
+{% endblock content %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..e173805 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,8 @@ from django.urls import path -from .views import home - +from .views import home, career_explorer_view, student_profile_view urlpatterns = [ path("", home, name="home"), + path("explore/", career_explorer_view, name="career_explorer"), # New URL pattern + path("profile/", student_profile_view, name="student_profile"), ] diff --git a/core/views.py b/core/views.py index c9aed12..ccbc6bf 100644 --- a/core/views.py +++ b/core/views.py @@ -4,6 +4,7 @@ import platform from django import get_version as django_version from django.shortcuts import render from django.utils import timezone +from .models import CareerPath, Skill # Import the new models def home(request): @@ -23,3 +24,43 @@ def home(request): "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), } return render(request, "core/index.html", context) + +def career_explorer_view(request): + """Render the career explorer page with all career paths and skills.""" + career_paths = CareerPath.objects.all().prefetch_related('required_skills') + skills = Skill.objects.all() + context = { + 'career_paths': career_paths, + 'skills': skills, + } + return render(request, 'core/career_explorer.html', context) + + +from django.contrib.auth.decorators import login_required +from django.shortcuts import redirect +from .forms import StudentProfileForm +from .models import StudentProfile + + +@login_required +def student_profile_view(request): + try: + student_profile = request.user.studentprofile + except StudentProfile.DoesNotExist: + student_profile = None + + if request.method == 'POST': + form = StudentProfileForm(request.POST, instance=student_profile) + if form.is_valid(): + profile = form.save(commit=False) + profile.user = request.user + profile.save() + return redirect('student_profile') # Redirect to the same page or a success page + else: + form = StudentProfileForm(instance=student_profile) + + context = { + 'form': form, + 'student_profile': student_profile + } + return render(request, 'core/student_profile_form.html', context) diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..ff6e6a9 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,53 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --primary-color: #0A2540; + --secondary-color: #FFFFFF; + --accent-color: #30C59B; + --background-color: #F6F9FC; + --text-color: #333333; } + +body { + font-family: 'Lato', sans-serif; + color: var(--text-color); + background-color: var(--background-color); +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Poppins', sans-serif; + color: var(--primary-color); +} + +/* Basic styling for the hero section to be implemented in index.html */ +.hero-section { + background: linear-gradient(180deg, var(--primary-color) 0%, #1A3E62 100%); + color: var(--secondary-color); + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-family: 'Poppins', sans-serif; + color: var(--secondary-color); + font-size: 3.5rem; + margin-bottom: 20px; +} + +.hero-section p { + font-size: 1.25rem; + margin-bottom: 30px; +} + +.hero-button { + background-color: var(--accent-color); + color: var(--secondary-color); + padding: 15px 30px; + border-radius: 5px; + text-decoration: none; + font-weight: bold; + font-size: 1.1rem; + transition: background-color 0.3s ease; +} + +.hero-button:hover { + background-color: #28a77f; /* Slightly darker accent for hover */ +} \ No newline at end of file diff --git a/static/images/icon-achieve.svg b/static/images/icon-achieve.svg new file mode 100644 index 0000000..aae2f1f --- /dev/null +++ b/static/images/icon-achieve.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/images/icon-assess.svg b/static/images/icon-assess.svg new file mode 100644 index 0000000..0e01dd0 --- /dev/null +++ b/static/images/icon-assess.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/images/icon-plan.svg b/static/images/icon-plan.svg new file mode 100644 index 0000000..b6d4433 --- /dev/null +++ b/static/images/icon-plan.svg @@ -0,0 +1,3 @@ + + + diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..ff6e6a9 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,53 @@ - :root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); + --primary-color: #0A2540; + --secondary-color: #FFFFFF; + --accent-color: #30C59B; + --background-color: #F6F9FC; + --text-color: #333333; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); + font-family: 'Lato', sans-serif; color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + background-color: var(--background-color); } + +h1, h2, h3, h4, h5, h6 { + font-family: 'Poppins', sans-serif; + color: var(--primary-color); +} + +/* Basic styling for the hero section to be implemented in index.html */ +.hero-section { + background: linear-gradient(180deg, var(--primary-color) 0%, #1A3E62 100%); + color: var(--secondary-color); + padding: 100px 0; + text-align: center; +} + +.hero-section h1 { + font-family: 'Poppins', sans-serif; + color: var(--secondary-color); + font-size: 3.5rem; + margin-bottom: 20px; +} + +.hero-section p { + font-size: 1.25rem; + margin-bottom: 30px; +} + +.hero-button { + background-color: var(--accent-color); + color: var(--secondary-color); + padding: 15px 30px; + border-radius: 5px; + text-decoration: none; + font-weight: bold; + font-size: 1.1rem; + transition: background-color 0.3s ease; +} + +.hero-button:hover { + background-color: #28a77f; /* Slightly darker accent for hover */ +} \ No newline at end of file diff --git a/staticfiles/images/icon-achieve.svg b/staticfiles/images/icon-achieve.svg new file mode 100644 index 0000000..aae2f1f --- /dev/null +++ b/staticfiles/images/icon-achieve.svg @@ -0,0 +1,3 @@ + + + diff --git a/staticfiles/images/icon-assess.svg b/staticfiles/images/icon-assess.svg new file mode 100644 index 0000000..0e01dd0 --- /dev/null +++ b/staticfiles/images/icon-assess.svg @@ -0,0 +1,3 @@ + + + diff --git a/staticfiles/images/icon-plan.svg b/staticfiles/images/icon-plan.svg new file mode 100644 index 0000000..b6d4433 --- /dev/null +++ b/staticfiles/images/icon-plan.svg @@ -0,0 +1,3 @@ + + +