Ürün6 Dakika Okuma
Mimio: Ergoterapistler İçin Seans ve Oyun Paneli
Mimio, ergoterapistlerin danışanlarını, seanslarını ve terapi oyunlarını tek panelde yönettiği bir uygulama. Başladığımda mesleği bilmiyordum; panelde ne var, nasıl kurdum ve bilmediğim bir alana araç yazarken ne öğrendim.


Bu Yazıda6 Bölüm
Mimio, çocuklar ve yetişkinlerle çalışan ergoterapistler için yaptığım bir klinik panel. Terapist danışanlarının profilini açıyor, haftalık program kuruyor, seansta tarayıcıdan açılan küçük terapi oyunlarını oynatıyor ve oyunun bıraktığı skor doğrudan danışanın dosyasına düşüyor. Zamanla o dosyadan bir ilerleme çizgisi çıkıyor; terapist aileye ya da kuruma rapor verirken o çizgiye bakıyor.
Fikir bir ergoterapistle sohbetten çıktı: seanslarda oynatılan oyunlar ölçülebilir veri üretsin, veri elle not defterine değil danışanın dosyasına gitsin. Mimio’yu yazmaya başladığımda ergoterapinin ne olduğunu tam bilmiyordum. Bu yazı o yüzden biraz da bilmediğin bir mesleğe araç yazmanın hikâyesi.
Panelde Neler Var
Danışanlar
Her danışanın profili: yaş grubu, birincil hedef, bağımsızlık düzeyi, etiketler. Bağımsızlık beş kademeli bir ölçek; tam bağımlıdan bağımsıza kadar.
Haftalık Plan
Danışan bazında bir terapi programı. Hangi gün hangi aktivite, hangi oyun; terapist sürükleyip yerleştiriyor.
Terapi Oyunları
Yedi oyun, her biri başka bir beceriye bakıyor. Oyun bitince skor, süre ve hata sayısı danışanın dosyasına yazılıyor.
Seans Notları
Oyun sonrası ya da bağımsız seans gözlemi. Serbest metin ya da mesleğin kendi biçimi olan SOAP notu.
İlerleme Raporu
Oyun skorları ve seans verileri üzerinden danışanın gelişimi; en iyi ve son skor yan yana, grafiklerle.
| Oyun | Baktığı Beceri |
|---|---|
| Sıra Hafızası | Görsel-uzamsal çalışma belleği |
| Kart Eşle | Görsel bellek ve sistematik arama |
| Mavi Nabız | Motor beceri, hız ve isabet dengesi |
| Komut Rotası | Yürütücü işlev, komut takibi ve kendini durdurabilme |
| Fark Avcısı | Görsel algı, figür ile zemini ayırma |
| Hedef Tarama | Seçici dikkat |
| Dizi Mantık | Örüntü tamamlama ve akıl yürütme |
Oyunların her biri ergoterapi literatüründe karşılığı olan bir paradigmaya dayanıyor; mesela Sıra Hafızası klasik Corsi blok testinin oyunlaştırılmış hâli. Bunu ben uydurmadım, mesleğin zaten kullandığı ölçekleri ekrana taşıdım. Panelde ayrıca yedi uzmanlık alanı için (pediatri, nörolojik rehabilitasyon, geriatri gibi) kanıta dayalı aktivite önerileri var.
Nasıl Kurdum
Next.js 15 ve TypeScript, stil Tailwind v4, hareket Framer Motion. Veritabanı Neon üzerinde Postgres ve HTTP sürücüsüyle konuşuyorum; Vercel’de her istek ayrı bir fonksiyonda çalıştığı için klasik bağlantı havuzu burada iş görmüyor. Parolalar Postgres’in kendi eklentisiyle bcrypt olarak hash’leniyor, oturum imzalı bir çerezde.
Panelde danışan adları, seans notları ve gelişim kayıtları duruyor. Bu bir hobi projesinin verisi gibi ele alınamaz. O yüzden bir şeyi bilerek yapmadım: hiçbir yere analitik, hata izleme ya da üçüncü taraf script koymadım. Bir hata raporu, içinde bir seans notuyla başka bir şirketin sunucusuna gidebilirdi.
Mesleğin Kendi Dili Vardı: SOAP
İlk hatamı seans notunda yaptım. İlk sürümde not tek bir serbest metin kutusuydu; oyun kaydının yanında bir metin sütunu, o kadar. Oysa bu mesleğin onlarca yıldır kullandığı bir not biçimi var ve ben onu ilk haftanın sonunda öğrendim.
| Harf | Ne Yazılır | Kim Söylüyor |
|---|---|---|
| S · Subjektif | Danışanın ya da ailesinin anlattığı | Danışan |
| O · Objektif | Seansta gözlenen, ölçülen | Terapist |
| A · Assessment | Bu ikisinden çıkan değerlendirme | Terapist |
| P · Plan | Bir sonraki adım | Terapist |
Sıra bir düşünme sırası: önce ne duyduğunu yaz, sonra ne gördüğünü, en son ne düşündüğünü. Yorum gözlemden ayrı duruyor. Benim tek kutumda bu ayrım yoktu; gözlem ile yorum aynı cümlede karışabiliyordu. SOAP panele girdi ama serbest notu da kaldırmadım. On dakikalık bir kontrol seansında dört bölümlük not yazmaya zorlanan biri büyük ihtimalle hiçbir şey yazmaz.
Bir mesleğe araç yazıyorsan, o meslek kendi kavramlarına çoktan ad vermiştir. Yeni bir sözlük icat etmene gerek yok; var olanı ekrana doğru yerleştirmen yeter.
Her Oyun Bir Kayıt Bırakıyor
Terapist için işe yarayan kısım oyunun kendisi değil, oyun bitince geride kalan kayıt. Her oyun için en iyi skor, son skor, kaç kez oynandığı ve en son ne zaman oynandığı tutuluyor.
export interface RemoteScoreSummary {
label: string;
best: number;
last: number;
sessions: number;
lastPlayedAt: string | null;
}En iyi ile son skorun ayrı tutulması küçük bir ayrıntı gibi duruyor. Yalnızca en iyiyi saklasan ilerleme hep yukarı gidiyor gibi görünür; yalnızca sonuncuyu saklasan kötü bir gün bütün tabloyu bozar. İkisi birlikte “iyi gününde ne yapıyor, bugün ne yaptı” sorusunu cevaplıyor.
Skorları yorumlayan tek bir yer var: ilerleme raporundaki oyun tablosu, en az üç seans varsa ilk ve son skoru karşılaştırıyor ve “artıyor”, “düşüyor” ya da “stabil” yazıyor. Bunun eşiği dört puan. O dört puanı bir terapist değil, ben seçtim ve bu rapor aileye gidiyor. Bu, projede hâlâ en az rahat olduğum karar.
Şema Her Hafta Değişti, Migration Yazmadım
Teknik tarafta en çok itiraz alacak karar bu. Alanı bilmediğim için şemayla ilgili tahminlerim tutmuyordu ve öğrendikçe değişiyordu. İlk haftanın sonunda danışan tablosuna zorluk düzeyi, arşivleme tarihi, etiketler ve doğum tarihi eklenmişti. Tek kişilik bir projede her değişiklikte migration üretip uygulamak, kazandırdığından fazlasını götürüyordu.
Bu yüzden şemayı, kaç kez çalışırsa çalışsın aynı sonucu veren SQL cümleleri olarak tuttum. Liste her yayından önce baştan sona çalışıyor: tablo varsa atlıyor, kolon yoksa ekliyor.
const SCHEMA_QUERIES = [
"CREATE EXTENSION IF NOT EXISTS pgcrypto",
`CREATE TABLE IF NOT EXISTS therapist_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
display_name TEXT NOT NULL UNIQUE,
clinic_name TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)`,
// Tablo zaten varsa CREATE atlanır, kolon eklemesi yine de çalışır.
"ALTER TABLE therapist_profiles ADD COLUMN IF NOT EXISTS specialty TEXT",
// ...
]ORM de yok; sorgular yer tutucularla düz SQL. Bunun karşılığında bazı şeylerden vazgeçtim: satırların tipini elle yazıyorum ve kolon adını yanlış yazarsam bunu derleme değil çalışma zamanı söylüyor. Kolon silmek ya da tip değiştirmek elle SQL demek. Altı tablolu, tek geliştiricili bir projede bu bedeli ödemeye razıyım.
Mimio · 6 Tablo
Düz SQL
Açılış Zili · 13+ Tablo
Drizzle
Kararı veren soru şuydu: aynı tabloyu kaç yerden okuyorum? Bir yerden okuyorsan tipi elle yazmak sorun değil. Birçok yerden okuyorsan tipin şemadan türemesi hatayı derlemede yakalıyor.
Ne Öğrendim
Bilmediğin bir alana araç yazarken en pahalı hata, alanı kendi kafandaki modele göre kurmak. SOAP altı gün sonra panele girdi ve ucuz atlattım. Aynı şey altı ay sonra olsaydı elimde düzensiz notlarla dolu bir veritabanı olurdu.
Şemanın belirsiz olması teknoloji seçimini de değiştirdi. “ORM kullanmalı mıyım” sorusunun cevabı projenin hangi aşamada olduğuna bağlıymış. Alanı öğrenip şema oturduğunda Mimio’yu Drizzle’a taşımak mantıklı olabilir. O gün henüz gelmedi.