JJK Tech
Portfolio

Une sélection de projets récents

Applications web et mobile conçues pour des PME et des indépendants, du cadrage à la mise en production.

Mission client

Awura Beauty — E-commerce cosmétique premium
type HairProfile = {
  type: "4A" | "4B" | "4C" | "3A-3C" | "locs";
  concern: "dryness" | "breakage" | "density" | "growth" | "scalp";
  goal: "hydration" | "length" | "definition" | "repair" | "volume";
};

export class HairDiagnosticService {
  constructor(
    private readonly catalog: ProductCatalogPort,
    private readonly quiz: DiagnosticQuizPort,
  ) {}

  async recommendRoutine(answers: DiagnosticAnswers): Promise<HairRoutine> {
    const profile = this.quiz.buildProfile(answers);
    const candidates = await this.catalog.findByHairProfile(profile);

    return {
      hairType: profile.type,
      products: candidates
        .filter((product) => product.matches(profile))
        .slice(0, 4)
        .map((product) => ({
          id: product.id,
          name: product.name,
          role: product.routineRole,
        })),
    };
  }
}
Mission clientNext.jsTypeScriptSupabaseStripe+4

Awura Beauty — E-commerce cosmétique premium

Site e-commerce de production pour une marque française de soins capillaires naturels dédiée aux cheveux texturés. Boutique, diagnostic capillaire, paiements, livraison et administration complète, dans une charte Luxury Organic (Vert Forêt / Doré).

MadBeauty — Marketplace de réservation beauté afro
class BookingPricing {
  static const depositRate = 0.20;
  static const platformFeeFromThirdBooking = 1.0;

  BookingQuote quote({
    required double servicePrice,
    required int completedBookings,
    required bool payDepositOnline,
    required StackedDiscounts discounts,
  }) {
    final price = discounts.applyInOrder(servicePrice);
    final platformFee =
        completedBookings >= 2 ? platformFeeFromThirdBooking : 0.0;

    if (!payDepositOnline) {
      return BookingQuote.payInPerson(
        price: price,
        platformFee: platformFee,
      );
    }

    final deposit = price * depositRate;
    return BookingQuote(
      deposit: deposit,
      remainderOnSite: price - deposit,
      platformFee: platformFee,
    );
  }
}

// Remises dans cet ordre : parrainage → VIP salon → fidélité
class StackedDiscounts {
  double applyInOrder(double price) {
    var current = price;
    current = applyReferral(current);
    current = applySalonVip(current);
    current = applyLoyalty(current);
    return current;
  }
}
Mission clientFlutterRiverpodSupabaseStripe+2

MadBeauty — Marketplace de réservation beauté afro

App iOS, Android et Web qui relie clientes et prestataires : découverte, Reels, réservation, acompte, messagerie temps réel et abonnement Pro.

Juna Pay — Transferts d'argent en Afrique
class TransferRepository {
  TransferRepository(this._api, this._secureStorage);

  final Dio _api;
  final FlutterSecureStorage _secureStorage;

  Future<TransferQuote> quote({
    required String corridor,
    required Money amount,
    required PaymentChannel channel,
  }) async {
    final token = await _secureStorage.read(key: 'access_token');

    final response = await _api.post<Map<String, dynamic>>(
      '/transfers/quote',
      data: {
        'corridor': corridor,
        'amount_cents': amount.cents,
        'channel': channel.name,
      },
      options: Options(headers: {'Authorization': 'Bearer $token'}),
    );

    return TransferQuote.fromJson(response.data!);
  }
}
Mission clientFintechFlutterReactSpring Boot+2

Juna Pay — Transferts d'argent en Afrique

App fintech de transferts Afrique–monde : Mobile Money, banques, paiements Chine et factures locales.

Produit fondateur

Projet personnel

Projet scolaire

Système de Gestion de Parc Informatique
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class EquipmentsController : ControllerBase
{
    private readonly IEquipmentService _equipmentService;

    public EquipmentsController(IEquipmentService equipmentService)
    {
        _equipmentService = equipmentService;
    }

    [HttpGet("maintenance-due")]
    [ProducesResponseType(typeof(IEnumerable<EquipmentDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetMaintenanceDue()
    {
        var equipments = await _equipmentService.GetDueForMaintenanceAsync(
            threshold: TimeSpan.FromDays(30));

        return Ok(equipments.Select(EquipmentDto.FromEntity));
    }

    [HttpPost("{id:guid}/maintenance")]
    public async Task<IActionResult> ScheduleMaintenance(Guid id, [FromBody] MaintenanceRequest request)
    {
        var success = await _equipmentService.ScheduleMaintenanceAsync(id, request.PlannedDate);
        return success ? NoContent() : NotFound();
    }
}
Projet scolaireASP.NET CoreBlazor ServerWPFSQL Server+3

Système de Gestion de Parc Informatique

Solution complète de gestion de parc informatique : équipements, maintenance préventive et licences, sur desktop, web et mobile.

Café Shop — Système de Gestion
@Service
public class StockAlertService {

    private static final int LOW_STOCK_THRESHOLD = 10;

    private final ProductRepository productRepository;
    private final NotificationService notificationService;

    public StockAlertService(ProductRepository productRepository,
                              NotificationService notificationService) {
        this.productRepository = productRepository;
        this.notificationService = notificationService;
    }

    @Scheduled(cron = "0 0 8 * * *")
    public void checkLowStock() {
        List<Product> lowStockItems = productRepository.findByQuantityLessThan(LOW_STOCK_THRESHOLD);

        lowStockItems.forEach(product ->
                notificationService.notifyManagers(
                        "Stock faible : " + product.getName() + " (" + product.getQuantity() + " restants)"));
    }

    @PreAuthorize("hasRole('MANAGER')")
    public void restockProduct(Long productId, int quantity) {
        Product product = productRepository.findById(productId)
                .orElseThrow(() -> new ProductNotFoundException(productId));
        product.setQuantity(product.getQuantity() + quantity);
        productRepository.save(product);
    }
}
Projet scolaireJava Spring BootReactJWTMySQL+2

Café Shop — Système de Gestion

Système de gestion complet pour un café : produits, commandes, employés, facturation et réservation de tables.

JLM Shop — Application Web E-commerce
class Cart
{
    private array $items = [];

    public function addItem(Product $product, int $quantity): void
    {
        $key = $product->getId();

        if (isset($this->items[$key])) {
            $this->items[$key]['quantity'] += $quantity;
        } else {
            $this->items[$key] = [
                'product' => $product,
                'quantity' => $quantity,
            ];
        }
    }

    public function getTotal(): float
    {
        return array_reduce($this->items, function (float $total, array $line) {
            $unitPrice = $line['product']->getPrice();
            return $total + ($unitPrice * $line['quantity']);
        }, 0.0);
    }

    public function checkout(PaymentGateway $gateway): PaymentResult
    {
        if (empty($this->items)) {
            throw new EmptyCartException();
        }

        return $gateway->charge($this->getTotal(), 'EUR');
    }
}
Projet scolairePHPMySQLSeleniumBootstrap+1

JLM Shop — Application Web E-commerce

Plateforme e-commerce complète : catalogue produits, panier, paiement et back-office d'administration.