Google Sheets belum diatur
Aplikasi ini memakai Google Sheets sebagai database, jadi belum bisa menyimpan apa pun sebelum diatur. Buka tab "✏️ Input & Tugas Rutin" → panel "Pengaturan Sinkronisasi Google Sheets" untuk mengatur URL-nya.
0 / 0 selesai
Belum ada aktivitas hari ini
Cari Tugas
⌕
Tidak ada tugas yang cocok.
⚠ Tugas Lewat Tanggal (Belum Selesai)
Hari Ini
□
Belum ada aktivitas tercatat untuk tanggal ini.
Tambah Aktivitas ke Timeline Harian
Tersimpan untuk tanggal:
Tugas Rutin (Harian & Bulanan)
0 tugas rutin tersimpan
Statistik Mingguan / Bulanan
Selesai per Hari
Selesai per Kategori
Ekspor Data
Unduh salinan seluruh data (dari cache yang sedang dimuat) sebagai file CSV.
Pengaturan Sinkronisasi Google Sheets (Database Utama)
Aplikasi ini membaca dan menulis langsung ke Google Sheets. URL Web App sudah ditanam sebagai bawaan (default) di dalam kode, jadi aplikasi ini otomatis terhubung di perangkat mana pun tanpa perlu tempel URL lagi. Ubah kolom di bawah hanya jika Anda ingin memakai spreadsheet lain.
Penting: karena tab "💰 Kas" menyimpan data baru (sheet "Kas"), pastikan Apps Script di spreadsheet Anda sudah memakai kode terbaru di bawah ini (deploy ulang / "Manage deployments" → naikkan versi baru) agar data Kas ikut tersimpan.
Buka Google Sheets baru (boleh kosong).
Menu Extensions → Apps Script.
Hapus kode default, tempel kode di bawah ini.
Klik Deploy → New deployment → Web app. Pilih "Execute as: Me" dan "Who has access: Anyone". (Kalau sudah pernah deploy sebelumnya, pilih "Manage deployments" → edit → naikkan versi baru.)
Salin URL Web App, tempel ke kolom di bawah, klik Simpan (opsional — hanya jika ganti spreadsheet).
function doGet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var type = (e.parameter && e.parameter.type) || 'tasks';
if (type === 'templates') {
var sheet = ss.getSheetByName('Templates');
if (!sheet || sheet.getLastRow() < 2) return jsonOutput([]);
var rows = sheet.getDataRange().getValues();
var data = [];
for (var i = 1; i < rows.length; i++) {
data.push({ id: rows[i][0], name: rows[i][1], category: rows[i][2], recurrence: rows[i][3] });
}
return jsonOutput(data);
}
if (type === 'cash') {
var sheet = ss.getSheetByName('Kas');
if (!sheet || sheet.getLastRow() < 2) return jsonOutput([]);
var rows = sheet.getDataRange().getValues();
var data = [];
for (var i = 1; i < rows.length; i++) {
var r = rows[i];
data.push({
id: r[0], date: fmtDate(r[1]), txType: r[2], name: r[3],
category: r[4], amount: r[5], fundId: r[6], note: r[7]
});
}
return jsonOutput(data);
}
var sheet = ss.getSheetByName('Data');
if (!sheet || sheet.getLastRow() < 2) return jsonOutput([]);
var rows = sheet.getDataRange().getValues();
var data = [];
for (var i = 1; i < rows.length; i++) {
var r = rows[i];
data.push({
id: r[0], date: fmtDate(r[1]), time: r[2], name: r[3], category: r[4],
priority: r[5], deadline: fmtDate(r[6]), status: r[7],
elapsed: r[8], timerStart: r[9], note: r[10]
});
}
return jsonOutput(data);
}
function fmtDate(v) {
if (v instanceof Date) return Utilities.formatDate(v, "GMT+8", "yyyy-MM-dd");
return v;
}
function jsonOutput(obj) {
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
var data = JSON.parse(e.postData.contents);
var ss = SpreadsheetApp.getActiveSpreadsheet();
if (data.type === 'template') {
var sheet = ss.getSheetByName('Templates') || ss.insertSheet('Templates');
if (sheet.getLastRow() === 0) sheet.appendRow(['ID', 'Nama', 'Kategori', 'Recurrence']);
var rows = sheet.getDataRange().getValues();
var rowIndex = -1;
for (var i = 1; i < rows.length; i++) { if (rows[i][0] === data.id) { rowIndex = i + 1; break; } }
if (data.action === 'delete') {
if (rowIndex > -1) sheet.deleteRow(rowIndex);
return jsonOutput({ result: 'deleted' });
}
var rowData = [data.id, data.name, data.category, data.recurrence];
if (rowIndex > -1) sheet.getRange(rowIndex, 1, 1, rowData.length).setValues([rowData]);
else sheet.appendRow(rowData);
return jsonOutput({ result: 'ok' });
}
if (data.type === 'cash') {
var sheet = ss.getSheetByName('Kas') || ss.insertSheet('Kas');
if (sheet.getLastRow() === 0) {
sheet.appendRow(['ID','Tanggal','Tipe','Nama/Keterangan','Kategori','Jumlah','FundID','Catatan','Diperbarui']);
}
var rows = sheet.getDataRange().getValues();
var rowIndex = -1;
for (var i = 1; i < rows.length; i++) { if (rows[i][0] === data.id) { rowIndex = i + 1; break; } }
if (data.action === 'delete') {
if (rowIndex > -1) sheet.deleteRow(rowIndex);
return jsonOutput({ result: 'deleted' });
}
var rowData = [data.id, data.date, data.txType, data.name, data.category || '', data.amount, data.fundId || '', data.note || '', new Date()];
if (rowIndex > -1) sheet.getRange(rowIndex, 1, 1, rowData.length).setValues([rowData]);
else sheet.appendRow(rowData);
return jsonOutput({ result: 'ok' });
}
var sheet = ss.getSheetByName('Data') || ss.insertSheet('Data');
if (sheet.getLastRow() === 0) {
sheet.appendRow(['ID','Tanggal','Waktu','Nama Tugas','Kategori','Prioritas','Tenggat','Status','Elapsed (detik)','Timer Mulai','Catatan','Diperbarui']);
}
var rows = sheet.getDataRange().getValues();
var rowIndex = -1;
for (var i = 1; i < rows.length; i++) { if (rows[i][0] === data.id) { rowIndex = i + 1; break; } }
if (data.action === 'delete') {
if (rowIndex > -1) sheet.deleteRow(rowIndex);
return jsonOutput({ result: 'deleted' });
}
var rowData = [data.id, data.date, data.time, data.name, data.category, data.priority, data.deadline, data.status, data.elapsed || 0, data.timerStart || '', data.note, new Date()];
if (rowIndex > -1) sheet.getRange(rowIndex, 1, 1, rowData.length).setValues([rowData]);
else sheet.appendRow(rowData);
return jsonOutput({ result: 'ok' });
}
URL bawaan sudah otomatis dipakai di semua perangkat. Kolom ini hanya untuk override manual, dan tetap tersimpan di penyimpanan browser perangkat ini bila diubah.
Riwayat Pekerjaan Selesai
Semua tugas yang sudah ditandai "Selesai", dikelompokkan per tanggal pengerjaan.
🕘
Belum ada tugas yang selesai dikerjakan.
Total Uang Masuk
Rp0
Total Pengeluaran
Rp0
Sisa Saldo
Rp0
+ Catat Uang Masuk
Contoh: dana yang diberikan Tn. Rudi untuk belanja bahan bangunan.
− Catat Pengeluaran
Pilih sumber dana agar saldonya otomatis berkurang.
Rekap per Sumber Dana
Klik nama sumber atau pengeluaran untuk lihat rincian.