Binaan Pengawas: Dewi Yuliani, S.Ag, M.A
1. Buat Google Spreadsheet baru dengan 3 sheet: "DataGuru", "DataAbsensi", dan "Token"
2. Di sheet "DataGuru" buat header: ID_Guru | Nama_Lengkap | Sekolah | Kecamatan | Tanggal_Dibuat
3. Di sheet "DataAbsensi" buat header: ID | ID_Guru | Nama_Lengkap | Sekolah | Kecamatan | Tanggal | Waktu | Timestamp
4. Di sheet "Token" buat header: Token | Tanggal_Dibuat | Waktu_Kadaluarsa | Status
5. Buka Extensions â Apps Script dan paste kode berikut:
function doPost(e) {
try {
const data = JSON.parse(e.postData.contents);
const ss = SpreadsheetApp.getActiveSpreadsheet();
if (data.action === 'addTeacher') {
const sheet = ss.getSheetByName('DataGuru');
sheet.appendRow([
data.data.id,
data.data.name,
data.data.school,
data.data.district,
new Date(data.data.createdAt)
]);
} else if (data.action === 'addAttendance') {
const sheet = ss.getSheetByName('DataAbsensi');
sheet.appendRow([
data.data.id,
data.data.userId,
data.data.namaLengkap,
data.data.sekolah,
data.data.kecamatan,
data.data.date,
data.data.time,
new Date(data.data.timestamp)
]);
} else if (data.action === 'saveToken') {
const sheet = ss.getSheetByName('Token');
// Clear previous tokens (mark as inactive)
const lastRow = sheet.getLastRow();
if (lastRow > 1) {
const range = sheet.getRange(2, 4, lastRow - 1, 1);
const values = range.getValues();
for (let i = 0; i < values.length; i++) {
values[i][0] = 'Tidak Aktif';
}
range.setValues(values);
}
// Add new token
sheet.appendRow([
data.data.token,
new Date(data.data.createdAt),
new Date(data.data.expiresAt),
'Aktif'
]);
}
return ContentService.createTextOutput('Success');
} catch (error) {
return ContentService.createTextOutput('Error: ' + error.toString());
}
}
function doGet(e) {
try {
const ss = SpreadsheetApp.getActiveSpreadsheet();
if (e.parameter.action === 'getTeachers') {
const sheet = ss.getSheetByName('DataGuru');
// Check if sheet has data
if (sheet.getLastRow() <= 1) {
return ContentService
.createTextOutput(JSON.stringify([]))
.setMimeType(ContentService.MimeType.JSON);
}
const data = sheet.getDataRange().getValues();
const rows = data.slice(1); // Skip header row
const teachers = rows.filter(row => row[0]).map(row => ({
id: row[0] ? row[0].toString() : '',
name: row[1] ? row[1].toString() : '',
school: row[2] ? row[2].toString() : '',
district: row[3] ? row[3].toString() : '',
createdAt: row[4] ? row[4] : new Date()
}));
return ContentService
.createTextOutput(JSON.stringify(teachers))
.setMimeType(ContentService.MimeType.JSON);
}
if (e.parameter.action === 'getActiveToken') {
const sheet = ss.getSheetByName('Token');
// Check if sheet has data
if (sheet.getLastRow() <= 1) {
return ContentService
.createTextOutput(JSON.stringify(null))
.setMimeType(ContentService.MimeType.JSON);
}
const data = sheet.getDataRange().getValues();
const rows = data.slice(1); // Skip header row
// Find active token that hasn't expired
const now = new Date();
const activeToken = rows.find(row => {
const status = row[3] ? row[3].toString() : '';
const expiresAt = row[2] ? new Date(row[2]) : null;
return status === 'Aktif' && expiresAt && expiresAt > now;
});
if (activeToken) {
const tokenData = {
token: activeToken[0] ? activeToken[0].toString() : '',
createdAt: activeToken[1] ? activeToken[1] : new Date(),
expiresAt: activeToken[2] ? activeToken[2] : new Date(),
status: activeToken[3] ? activeToken[3].toString() : ''
};
return ContentService
.createTextOutput(JSON.stringify(tokenData))
.setMimeType(ContentService.MimeType.JSON);
} else {
return ContentService
.createTextOutput(JSON.stringify(null))
.setMimeType(ContentService.MimeType.JSON);
}
}
if (e.parameter.action === 'getAttendance') {
const sheet = ss.getSheetByName('DataAbsensi');
// Check if sheet has data
if (sheet.getLastRow() <= 1) {
return ContentService
.createTextOutput(JSON.stringify([]))
.setMimeType(ContentService.MimeType.JSON);
}
const data = sheet.getDataRange().getValues();
const rows = data.slice(1); // Skip header row
const attendance = rows.filter(row => row[0]).map(row => ({
id: row[0] ? row[0] : '',
userId: row[1] ? row[1].toString() : '',
namaLengkap: row[2] ? row[2].toString() : '',
sekolah: row[3] ? row[3].toString() : '',
kecamatan: row[4] ? row[4].toString() : '',
date: row[5] ? row[5].toString() : '',
time: row[6] ? row[6].toString() : '',
timestamp: row[7] ? row[7] : new Date()
}));
return ContentService
.createTextOutput(JSON.stringify(attendance))
.setMimeType(ContentService.MimeType.JSON);
}
return ContentService.createTextOutput('No action specified');
} catch (error) {
return ContentService.createTextOutput('Error: ' + error.toString());
}
}
6. Deploy sebagai Web App dengan akses "Anyone" dan copy URL-nya
7. Ganti URL di kode JavaScript dengan URL Web App Anda
8. PENTING: Pastikan sheet "Token" sudah dibuat dengan header yang benar!
Selamat datang,
đĄ Minta token dari admin untuk mengaktifkan scanner
Belum ada data absensi hari ini
Status: -
| No | No Akun | Nama Lengkap | Sekolah | Kecamatan | Waktu Absen | Status |
|---|---|---|---|---|---|---|
| Belum ada data absensi | ||||||
| No Akun | Nama Lengkap | Sekolah | Kecamatan |
|---|---|---|---|
| Belum ada data guru | |||