From 8728594347a3fd7980a53e6f9f00abe6bba0a916 Mon Sep 17 00:00:00 2001 From: Jalil Arfaoui Date: Wed, 11 Mar 2026 15:12:53 +0100 Subject: [PATCH] =?UTF-8?q?Page=20parcours=20:=20logos=20entreprises,=20ba?= =?UTF-8?q?dges=20de=20type=20color=C3=A9s,=20dur=C3=A9es=20calcul=C3=A9es?= =?UTF-8?q?,=20support=20light/dark=20mode=20(FR/EN/AR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/images/companies/araymond.png | Bin 0 -> 2858 bytes src/assets/images/companies/champollion.png | Bin 0 -> 2548 bytes src/assets/images/companies/dismoi.png | Bin 0 -> 1463 bytes src/assets/images/companies/libeo.png | Bin 0 -> 2675 bytes src/assets/images/companies/obat.png | Bin 0 -> 1222 bytes src/assets/images/companies/urssaf.png | Bin 0 -> 1358 bytes src/assets/images/companies/veepee.png | Bin 0 -> 1281 bytes src/content.config.ts | 1 + src/content/experiences/araymond.ar.md | 1 + src/content/experiences/araymond.en.md | 1 + src/content/experiences/araymond.md | 1 + src/content/experiences/champollion.ar.md | 1 + src/content/experiences/champollion.en.md | 1 + src/content/experiences/champollion.md | 1 + src/content/experiences/dismoi.ar.md | 1 + src/content/experiences/dismoi.en.md | 1 + src/content/experiences/dismoi.md | 1 + src/content/experiences/libeo.ar.md | 1 + src/content/experiences/libeo.en.md | 1 + src/content/experiences/libeo.md | 1 + src/content/experiences/obat.ar.md | 1 + src/content/experiences/obat.en.md | 1 + src/content/experiences/obat.md | 1 + src/content/experiences/urssaf.ar.md | 1 + src/content/experiences/urssaf.en.md | 1 + src/content/experiences/urssaf.md | 1 + src/content/experiences/veepee-dev.ar.md | 1 + src/content/experiences/veepee-dev.en.md | 1 + src/content/experiences/veepee-dev.md | 1 + src/content/experiences/veepee-lead.ar.md | 1 + src/content/experiences/veepee-lead.en.md | 1 + src/content/experiences/veepee-lead.md | 1 + src/layouts/main.astro | 8 +- src/pages/ar/برمجة/مسار.astro | 172 +++++++++++++++++--- src/pages/code/parcours.astro | 172 +++++++++++++++++--- src/pages/en/code/career.astro | 172 +++++++++++++++++--- 36 files changed, 488 insertions(+), 61 deletions(-) create mode 100644 src/assets/images/companies/araymond.png create mode 100644 src/assets/images/companies/champollion.png create mode 100644 src/assets/images/companies/dismoi.png create mode 100644 src/assets/images/companies/libeo.png create mode 100644 src/assets/images/companies/obat.png create mode 100644 src/assets/images/companies/urssaf.png create mode 100644 src/assets/images/companies/veepee.png diff --git a/src/assets/images/companies/araymond.png b/src/assets/images/companies/araymond.png new file mode 100644 index 0000000000000000000000000000000000000000..a4660ed74b27552904ca7b5ae563053d9ee53f02 GIT binary patch literal 2858 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 IM6N<$f-YKQ7ytkO literal 0 HcmV?d00001 diff --git a/src/assets/images/companies/champollion.png b/src/assets/images/companies/champollion.png new file mode 100644 index 0000000000000000000000000000000000000000..c618ebb4c7a702bdc2235b1e86489081038aa966 GIT binary patch literal 2548 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 KMNUMnLSTaD&)~8E literal 0 HcmV?d00001 diff --git a/src/assets/images/companies/dismoi.png b/src/assets/images/companies/dismoi.png new file mode 100644 index 0000000000000000000000000000000000000000..3c44aac123d95266d4720c8eca2662533ea07559 GIT binary patch literal 1463 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/companies/obat.png b/src/assets/images/companies/obat.png new file mode 100644 index 0000000000000000000000000000000000000000..1f3f81f06edc0c2d9ea85795cdf9589284498fb2 GIT binary patch literal 1222 zcmV;%1UdVOP)C0000dP)t-sM{rCy zqVhPR@;IXMIHK}6qVhPR@;IXMIHK}6qVhPR@;IXMIim9S-?PX7000bhQchC<^otYd zzSTBMXCtIvV7&8Z*zx#{#359h| zhq(&|Gsol*^8(N4x;h@iF|xCfQ}A$Cih?lMwgwVl=t4{e>Zg! z{=)||C@}!#T`t2ym^0=7Vy>79K-?>VuK@L3e&w<)gJ6HbT}0$Y0GkutdmWm!eBvE) z7Y%qGkUt)ko@Qo3@L$&wPXHdW-yv|mibik>$TMLyRmB~N z;D`l=hyf~9Ju@s+cBkJ0AWX2#{!R#pbKf@t;e+2{lSzgM@BecnLId_OfuRY1no55F z2o0o$M;^iqb{zx=vswWw5lXPz*;oTl=@S0m!YM$ z3V?{RtA}BTtpXsD{Z+s)6;UlNuoIMU4)Rb$PT<8I8hKVRi~{W%Aasx;K}0Q}hA4ax z;*hNn*`OC`{U9YPJs}%xxdsk`31^znPc?ly2LLbv+nyzU&ktqPe@=&CSrv|(ub2$0sd4{+C43Y8Ch2H@WNzxX@(KD`vF;;;_@7J z`FH{#%k$w66c}Tp2w3kw9UrNPM$n#icYUUVNALPI_%W~JL*=ess%2fT1oEkN|2^ul zy4Dle=MH+VSI1RHH7$v;hX?-rh6UX>@6xh4yVr=O)rWV{o%0TDyN~!nH!hWMj!eMSP7{eYTx$T2ck^A)LPRFYp+J{(v zImYvF!

-*?p2pXpm|6C|6d(;9<7$<9zZ1)i?Zco^dwyZ^U2y?zn$G ka{2uLaasRYzG40U9}4Z4TGWvj=Kufz07*qoM6N<$f(-dR^#A|> literal 0 HcmV?d00001 diff --git a/src/assets/images/companies/urssaf.png b/src/assets/images/companies/urssaf.png new file mode 100644 index 0000000000000000000000000000000000000000..86268655d69b0b041a55472127bda05537d987b4 GIT binary patch literal 1358 zcmV-U1+n^xP)C0001-P)t-s|NsBc z-Sm*N<^XZd9?H{;u;l=1%+%oZsKV%%x9H5;^8m=v0B+3yY|ZTP`}zC+-skrKb>Z*lpS0puOqg@A}H&^t;#b zS=8Hxx#wb@+)InrHiOh2e9-`8%N~W*g|g$K=vdH;8tPEf!seX5k`T%_*i8$w3B#^B6njQ!^6w%^`a zpHTqQxWN4l;Tc63Y#;mQ$L=^l7?t@a2n(nlS0?lscNk!9u}=tMxe|ic`+nXY1DGxB z{z)2ye$d;Cf^Uxki2g>AH3sXOvtoM)K#0Fgptsq|qX0t0-ee&v`+(r)ywn~5m_`_Y zwCoC4ls*3 zf5#gi9==5qAOKvVQ*aM(7zNjI1IPeZq`x_m-XGmuVE%Rh@EkhU+mrehDgY6HtU;55 zwnjs2>@{nKmao`0MI7P01yXKx{+$K1Y`h>E~dMMbj6$l z5CHmi<~^rB?UN;dTu?x(>H9lL6JCXI0OU~IufxFGAP-=sfslp6I~iMp;5A+OHDzk= zh5MiUL)IXCQ#!W<;rN!2JBbK@#-yYjGdH#5AZ9MB8=4b*$3e_0F0~vgI?tTwlQFe zpn3pX4H~gkNCR~3{&W$r0741yML+{cf4;y@0v2Ftn}eUp0STanl0SPMu>kfaOvUAZ z1dw`w&jAM@_CO+CWdy_$q(eXfKmj1P5(=OT{tXio0tNu+!JU{Bi2{HsfD8cv09HU6 z0(=$_0M=zNqX13<4j>*wpGyJ^09PQH1Q>uxKq7P)zyMSN5`miu2%vhbKUxML0N#NI zX@~#rP^pkYL;#fiZOjq_fB*nc9kKx^0vSND4fugTtOFU~llgy_FLa{>phjQw z7q?^yz;-1DDzFxU6+kWN`Bx-uOM?wS4Zl!+A7lwaIlzg&{!V&T7KAbYrF!rJh9Q(R zWHEs14o_>JC@4fI0#L0A>=S7}Ukf<^rCOtE>{AVVw`T!RYB_YjI(Y=?grS!QP)6OM zTj7`g2;sY~y8|#WZ*`Z;&d5Dg*Mkr`2nI&IrtABwLB(;eRjXF5TD2C0000UP)t-sM{rE- z0FCVcjO_r7?EsAJ0F3PbjO_r7?EsAI0E{B6sHy+}010$bPE!CB&+4<0O)hN|!i}i_ z00fCiL_t(|ob6lLvZWvlJZvHU{|{ef4K9EhwCa|rd6+uIm?r6TA~L_~_WqLp*Lb+j41YwEz zN~PFyKpc9~6+zHB0m{&{uvsQ}N^cQz6!CBHbH8&B44Hzt?r9oSM1vs~+;xzB5q@u) zlaD-vNN`$i1BJwF5V-Jo#o#4D&Oo`bH3G;#@)n{lwnz*L|C+AmWMS?@o6J%Kk$C() zIeFO*AXI=OKkS;Vw=Fr@VHWAqsq(m4mnSYep~ zM2;P=kY$XR0YsKp3fq)REH4M3++J--kZQpTAXZ^*#u*AA#8=h&Yg}V906rxQ53i1y zF$XXLfNpXykI0@Uwz>WafNFn_vl#)vHxFnU-6H@+n4r1-0svKiU;v;q0KOLkO$mNv z1yivq+*bkAABa>4kW~f(fSq}i8c+a+m4kf%ELAJX%E6G{*6S{ffZ}~QHH61Yz4)Y=egNPp!+cPRJpfc}nWot{P8)PIqhD;9OAWA}QmS@47EuO(Sp?j} zWg9>e3p3(tfo_jj7^=_)sFsxmI5nAVLJ^<~fG~=&5`}Ol<8=UjXmHgi{LwZO6D=66 zlE@t|lb!;&tP`?FySu!j&WCW-2l_)2oLx&BM)cbN1eBkKs!2t!0ts{iyEKy`Tk zg$x*&|L}agjs8{VZ0oxfOcKbaqZ=0U-+fWV{R3kZu1_ql*=ZX2Lorl_$N%{{_6(3y zI#j>e2F~un2O!tY-AgQ9Ncx4;PYc=qZ3#9_*(K{ z;19dxEsu&?K$hNd?q?S4PlJNIsp+n1`Lf}bTE*tg@O#zk(y~U9%|CptTUgAre_->+ z-k%8l$~%zAOXNNGX*#$0d_c*k|6hjyowh!|pFX section h1, [data-facet="code"] > section h2, - [data-facet="code"] > section h3, - [data-facet="code"] > section strong { + [data-facet="code"] > section h3:not(.exp-card h3):not(.facet-card h3), + [data-facet="code"] > section strong:not(.exp-card strong):not(.facet-card strong) { color: white !important; } @@ -72,8 +72,8 @@ const locale = pathname.startsWith("/en") text-decoration-color: white !important; } - [data-facet="code"] > section > :not(.facet-card) p, - [data-facet="code"] > section > :not(.facet-card) li { + [data-facet="code"] > section p:not(.exp-card p):not(.facet-card p), + [data-facet="code"] > section li:not(.exp-card li):not(.facet-card li) { color: rgba(255, 255, 255, 0.75) !important; } diff --git a/src/pages/ar/برمجة/مسار.astro b/src/pages/ar/برمجة/مسار.astro index f33324e..9c527c2 100644 --- a/src/pages/ar/برمجة/مسار.astro +++ b/src/pages/ar/برمجة/مسار.astro @@ -1,16 +1,37 @@ --- import { getCollection, render } from "astro:content"; +import { Image } from "astro:assets"; import Layout from "../../../layouts/main.astro"; +const logos = import.meta.glob<{ default: ImageMetadata }>('../../../assets/images/companies/*.png', { eager: true }); + +function getLogo(filename?: string) { + if (!filename) return null; + const key = `../../../assets/images/companies/${filename}`; + return logos[key]?.default ?? null; +} + +function getInitials(company: string) { + return company.split(/[\s-]+/).map(w => w[0]).filter(Boolean).slice(0, 2).join('').toUpperCase(); +} + const locale = "ar"; const experiences = (await getCollection("experiences")) .filter((e) => e.data.lang === locale && !e.data.draft) .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); -const typeIcons: Record = { - employment: '🏢', freelance: '💼', teaching: '🎓', - community: '🤝', entrepreneurship: '🚀', +const typeLabels: Record = { + employment: 'وظيفة', freelance: 'مستقل', teaching: 'تدريس', + community: 'مجتمع', entrepreneurship: 'ريادة أعمال', +}; + +const typeColors: Record = { + employment: { badge: 'type-badge-blue', border: 'type-border-blue', dot: 'bg-blue-400 border-blue-400/50' }, + freelance: { badge: 'type-badge-amber', border: 'type-border-amber', dot: 'bg-amber-400 border-amber-400/50' }, + teaching: { badge: 'type-badge-emerald', border: 'type-border-emerald', dot: 'bg-emerald-400 border-emerald-400/50' }, + community: { badge: 'type-badge-pink', border: 'type-border-pink', dot: 'bg-pink-400 border-pink-400/50' }, + entrepreneurship: { badge: 'type-badge-purple', border: 'type-border-purple', dot: 'bg-purple-400 border-purple-400/50' }, }; function formatMonth(dateStr: string) { @@ -18,6 +39,17 @@ function formatMonth(dateStr: string) { return new Date(parseInt(year), parseInt(month) - 1) .toLocaleDateString('ar-SA', { year: 'numeric', month: 'short' }); } + +function computeDuration(startStr: string, endStr?: string) { + const [sy, sm] = startStr.split('-').map(Number); + const end = endStr ? endStr.split('-').map(Number) : [new Date().getFullYear(), new Date().getMonth() + 1]; + const totalMonths = (end[0] - sy) * 12 + (end[1] - sm); + const years = Math.floor(totalMonths / 12); + const months = totalMonths % 12; + if (years === 0) return `${months} أشهر`; + if (months === 0) return `${years} سنة`; + return `${years} سنة ${months} أشهر`; +} --- +

- {isOngoing &&
} + {isOngoing &&
}
-
-
- - {typeIcons[exp.data.type] || '💼'} {start} — {end} +
+ {getLogo(exp.data.logo) ? ( + + ) : ( +
+ {getInitials(exp.data.company)} +
+ )} + +
+ + {label} - {exp.data.location && · {exp.data.location}} + + {start} — {end} + + · {duration} + {exp.data.location && · {exp.data.location}}
-

{exp.data.role}

-

+

{exp.data.role}

+

{exp.data.companyUrl ? ( - {exp.data.company} + {exp.data.company} ) : exp.data.company}

-
+
{exp.data.technologies && exp.data.technologies.length > 0 && (
{exp.data.technologies.map((tech: string) => ( - + {tech} ))} @@ -92,3 +149,80 @@ function formatMonth(dateStr: string) {
+ + diff --git a/src/pages/code/parcours.astro b/src/pages/code/parcours.astro index 7c23059..fdf983a 100644 --- a/src/pages/code/parcours.astro +++ b/src/pages/code/parcours.astro @@ -1,16 +1,37 @@ --- import { getCollection, render } from "astro:content"; +import { Image } from "astro:assets"; import Layout from "../../layouts/main.astro"; +const logos = import.meta.glob<{ default: ImageMetadata }>('../../assets/images/companies/*.png', { eager: true }); + +function getLogo(filename?: string) { + if (!filename) return null; + const key = `../../assets/images/companies/${filename}`; + return logos[key]?.default ?? null; +} + +function getInitials(company: string) { + return company.split(/[\s-]+/).map(w => w[0]).filter(Boolean).slice(0, 2).join('').toUpperCase(); +} + const locale = "fr"; const experiences = (await getCollection("experiences")) .filter((e) => e.data.lang === locale && !e.data.draft) .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); -const typeIcons: Record = { - employment: '🏢', freelance: '💼', teaching: '🎓', - community: '🤝', entrepreneurship: '🚀', +const typeLabels: Record = { + employment: 'Emploi', freelance: 'Freelance', teaching: 'Enseignement', + community: 'Communauté', entrepreneurship: 'Entrepreneuriat', +}; + +const typeColors: Record = { + employment: { badge: 'type-badge-blue', border: 'type-border-blue', dot: 'bg-blue-400 border-blue-400/50' }, + freelance: { badge: 'type-badge-amber', border: 'type-border-amber', dot: 'bg-amber-400 border-amber-400/50' }, + teaching: { badge: 'type-badge-emerald', border: 'type-border-emerald', dot: 'bg-emerald-400 border-emerald-400/50' }, + community: { badge: 'type-badge-pink', border: 'type-border-pink', dot: 'bg-pink-400 border-pink-400/50' }, + entrepreneurship: { badge: 'type-badge-purple', border: 'type-border-purple', dot: 'bg-purple-400 border-purple-400/50' }, }; function formatMonth(dateStr: string) { @@ -18,6 +39,17 @@ function formatMonth(dateStr: string) { return new Date(parseInt(year), parseInt(month) - 1) .toLocaleDateString('fr-FR', { year: 'numeric', month: 'short' }); } + +function computeDuration(startStr: string, endStr?: string) { + const [sy, sm] = startStr.split('-').map(Number); + const end = endStr ? endStr.split('-').map(Number) : [new Date().getFullYear(), new Date().getMonth() + 1]; + const totalMonths = (end[0] - sy) * 12 + (end[1] - sm); + const years = Math.floor(totalMonths / 12); + const months = totalMonths % 12; + if (years === 0) return `${months} mois`; + if (months === 0) return `${years} an${years > 1 ? 's' : ''}`; + return `${years} an${years > 1 ? 's' : ''} ${months} mois`; +} --- +
- {isOngoing &&
} + {isOngoing &&
}
-
-
- - {typeIcons[exp.data.type] || '💼'} {start} — {end} +
+ {getLogo(exp.data.logo) ? ( + + ) : ( +
+ {getInitials(exp.data.company)} +
+ )} + +
+ + {label} - {exp.data.location && · {exp.data.location}} + + {start} — {end} + + · {duration} + {exp.data.location && · {exp.data.location}}
-

{exp.data.role}

-

+

{exp.data.role}

+

{exp.data.companyUrl ? ( - {exp.data.company} + {exp.data.company} ) : exp.data.company}

-
+
{exp.data.technologies && exp.data.technologies.length > 0 && (
{exp.data.technologies.map((tech: string) => ( - + {tech} ))} @@ -92,3 +149,80 @@ function formatMonth(dateStr: string) {
+ + diff --git a/src/pages/en/code/career.astro b/src/pages/en/code/career.astro index 0bec84b..aad30c5 100644 --- a/src/pages/en/code/career.astro +++ b/src/pages/en/code/career.astro @@ -1,16 +1,37 @@ --- import { getCollection, render } from "astro:content"; +import { Image } from "astro:assets"; import Layout from "../../../layouts/main.astro"; +const logos = import.meta.glob<{ default: ImageMetadata }>('../../../assets/images/companies/*.png', { eager: true }); + +function getLogo(filename?: string) { + if (!filename) return null; + const key = `../../../assets/images/companies/${filename}`; + return logos[key]?.default ?? null; +} + +function getInitials(company: string) { + return company.split(/[\s-]+/).map(w => w[0]).filter(Boolean).slice(0, 2).join('').toUpperCase(); +} + const locale = "en"; const experiences = (await getCollection("experiences")) .filter((e) => e.data.lang === locale && !e.data.draft) .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); -const typeIcons: Record = { - employment: '🏢', freelance: '💼', teaching: '🎓', - community: '🤝', entrepreneurship: '🚀', +const typeLabels: Record = { + employment: 'Employment', freelance: 'Freelance', teaching: 'Teaching', + community: 'Community', entrepreneurship: 'Entrepreneurship', +}; + +const typeColors: Record = { + employment: { badge: 'type-badge-blue', border: 'type-border-blue', dot: 'bg-blue-400 border-blue-400/50' }, + freelance: { badge: 'type-badge-amber', border: 'type-border-amber', dot: 'bg-amber-400 border-amber-400/50' }, + teaching: { badge: 'type-badge-emerald', border: 'type-border-emerald', dot: 'bg-emerald-400 border-emerald-400/50' }, + community: { badge: 'type-badge-pink', border: 'type-border-pink', dot: 'bg-pink-400 border-pink-400/50' }, + entrepreneurship: { badge: 'type-badge-purple', border: 'type-border-purple', dot: 'bg-purple-400 border-purple-400/50' }, }; function formatMonth(dateStr: string) { @@ -18,6 +39,17 @@ function formatMonth(dateStr: string) { return new Date(parseInt(year), parseInt(month) - 1) .toLocaleDateString('en-US', { year: 'numeric', month: 'short' }); } + +function computeDuration(startStr: string, endStr?: string) { + const [sy, sm] = startStr.split('-').map(Number); + const end = endStr ? endStr.split('-').map(Number) : [new Date().getFullYear(), new Date().getMonth() + 1]; + const totalMonths = (end[0] - sy) * 12 + (end[1] - sm); + const years = Math.floor(totalMonths / 12); + const months = totalMonths % 12; + if (years === 0) return `${months} mo`; + if (months === 0) return `${years} yr${years > 1 ? 's' : ''}`; + return `${years} yr${years > 1 ? 's' : ''} ${months} mo`; +} --- +
- {isOngoing &&
} + {isOngoing &&
}
-
-
- - {typeIcons[exp.data.type] || '💼'} {start} — {end} +
+ {getLogo(exp.data.logo) ? ( + + ) : ( +
+ {getInitials(exp.data.company)} +
+ )} + +
+ + {label} - {exp.data.location && · {exp.data.location}} + + {start} — {end} + + · {duration} + {exp.data.location && · {exp.data.location}}
-

{exp.data.role}

-

+

{exp.data.role}

+

{exp.data.companyUrl ? ( - {exp.data.company} + {exp.data.company} ) : exp.data.company}

-
+
{exp.data.technologies && exp.data.technologies.length > 0 && (
{exp.data.technologies.map((tech: string) => ( - + {tech} ))} @@ -92,3 +149,80 @@ function formatMonth(dateStr: string) {
+ +