--- import { getCollection } from "astro:content"; import { getLocalizedCollection } from "../../../utils/content-i18n"; import { Image } from "astro:assets"; import Layout from "../../../layouts/main.astro"; import Link from "../../../components/Link.astro"; import FeaturedRecommendation from "../../../components/code/FeaturedRecommendation.astro"; import ProjectCard from "../../../components/code/ProjectCard.astro"; import ValueItem from "../../../components/code/ValueItem.astro"; import LinkedInIcon from "../../../components/icons/LinkedInIcon.astro"; import MaltIcon from "../../../components/icons/MaltIcon.astro"; import StackOverflowIcon from "../../../components/icons/StackOverflowIcon.astro"; import GitHubIcon from "../../../components/icons/GitHubIcon.astro"; import ForgejoIcon from "../../../components/icons/ForgejoIcon.astro"; import { getProjectBaseSlug, getProjectsBasePath } from "../../../utils/i18n"; import logoTiqa from "../../../assets/images/logo-tiqa-blanc.png"; const locale = "ar"; const projectsBasePath = getProjectsBasePath(locale); const experiences = (await getLocalizedCollection("experiences", locale)) .filter((e) => !e.data.draft) .sort((a, b) => { const endA = a.data.endDate ?? '9999-12'; const endB = b.data.endDate ?? '9999-12'; if (endA !== endB) return endB > endA ? 1 : -1; return b.data.startDate > a.data.startDate ? 1 : -1; }); const recentExperiences = experiences.filter((e) => e.data.featured).slice(0, 4); const projects = (await getLocalizedCollection("projects", locale)) .filter((p) => !p.data.draft && p.data.category === "dev" && p.data.featured) .sort((a, b) => b.data.date!.getTime() - a.data.date!.getTime()); const recommendations = (await getCollection("recommendations")) .filter((r) => r.data.featured) .sort((a, b) => b.data.date.getTime() - a.data.date.getTime()); const recommendationTexts = recommendations.map((rec) => ({ ...rec, text: rec.body || '', })); function formatMonth(dateStr: string) { const [year, month] = dateStr.split('-'); return new Date(parseInt(year), parseInt(month) - 1) .toLocaleDateString('ar-SA', { year: 'numeric', month: 'short' }); } ---
مطوّر مستقل · ألبي

حِرَفيّ البرمجيات

TDD، Clean Code، Domain-Driven Design: هذه طريقتي في بناء البرمجيات. أرافق الفرق كمطوّر أول، أو قائد تقني، أو مدرب تقني. أدواتي: TypeScript/JavaScript، وكذلك PHP وElixir.

ما يميّزني ربّما: أهتمّ بجودة الكود بقدر اهتمامي بما ينتجه. أفضّل البرمجيات الحرّة والأدوات التي تلبّي احتياجات حقيقية. أتساءل أيضًا عن التحيّزات التي ندرجها في الكود، والتي تُديم علاقات اجتماعية تستحقّ المساءلة.

أُدرّس البرمجة في جامعة شامبوليون وأنشّط مجتمع Software Crafters Albi منذ 2018.

المسار

← عرض الكل
{recentExperiences.map((exp) => { const isOngoing = !exp.data.endDate; const start = formatMonth(exp.data.startDate); const end = exp.data.endDate ? formatMonth(exp.data.endDate) : 'الحالي'; return (
{isOngoing && (
)} {start} — {end}

{exp.data.role}

{exp.data.companyUrl ? ( {exp.data.company} ) : exp.data.company} {exp.data.location && ` · ${exp.data.location}`}

); })}

المشاريع

← عرض الكل
{projects.map((project) => ( ))}
{recommendationTexts.length > 0 && (

التوصيات

← عرض الكل
{recommendationTexts.map((rec) => ( ))}
)}

القيم والمنهج

    حركة Software Craftsmanship الفائدة الاجتماعية للمطوّر الفخر بالعمل، دون غرور منهج Domain Driven Design تنظيم أجايل: التكرار والتحسين المستمر

المجتمع والتدريس

أنشّط مجتمع Software Crafters Albi منذ 2018. أستاذ هندسة البرمجيات في جامعة شامبوليون في ألبي منذ 2019.

شعار Tiqa

SAS Tiqa
12, rue Fabre d'Églantine — 81 000 Albi, France
811 917 871 RCS Albi