359 lines
15 KiB
PHP
359 lines
15 KiB
PHP
<?= $this->extend('layout/main_layout') ?>
|
||
<?= $this->section('content') ?>
|
||
<?php
|
||
$hasClass = !empty($classSectionId);
|
||
$assignedClassName = $classSectionName ?? '';
|
||
$sundayOptions = $sundayOptions ?? [];
|
||
$defaultWeekStart = $defaultWeekStart ?? ($sundayOptions[0] ?? '');
|
||
$weekStartSelected = set_value('week_start', $defaultWeekStart);
|
||
$weekEndValue = set_value('week_end');
|
||
if (!$weekEndValue && $weekStartSelected) {
|
||
try {
|
||
$dt = new \DateTime($weekStartSelected);
|
||
$dt->modify('+6 days');
|
||
$weekEndValue = $dt->format('Y-m-d');
|
||
} catch (\Exception $e) {
|
||
$weekEndValue = '';
|
||
}
|
||
}
|
||
$weekEndLabel = '';
|
||
if ($weekEndValue) {
|
||
try {
|
||
$weekEndLabel = (new \DateTime($weekEndValue))->format('M d, Y');
|
||
} catch (\Exception $e) {
|
||
$weekEndLabel = 'Week end';
|
||
}
|
||
} else {
|
||
$weekEndLabel = 'Select a week';
|
||
}
|
||
?>
|
||
<div class="py-4">
|
||
<div class="d-flex flex-wrap align-items-center justify-content-between mb-3">
|
||
<div>
|
||
<h3 class="mb-0">
|
||
<?= esc($classSectionName ? "Class {$classSectionName} Progress Submission" : 'Class Progress Submission') ?>
|
||
</h3>
|
||
<div class="text-muted">Submit weekly progress for a single subject</div>
|
||
</div>
|
||
<a href="<?= base_url('teacher/progress/history') ?>" class="btn btn-outline-secondary">My Submissions</a>
|
||
</div>
|
||
|
||
<?php if (session()->getFlashdata('success')): ?>
|
||
<div class="alert alert-success"><?= esc(session()->getFlashdata('success')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('error')): ?>
|
||
<div class="alert alert-danger"><?= esc(session()->getFlashdata('error')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('errors')): ?>
|
||
<div class="alert alert-danger">
|
||
<ul class="mb-0">
|
||
<?php foreach (session()->getFlashdata('errors') as $error): ?>
|
||
<li><?= esc($error) ?></li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form action="<?= base_url('teacher/progress/store') ?>" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="class_section_id" value="<?= esc($classSectionId ?? '') ?>">
|
||
<div class="row g-3">
|
||
<div class="col">
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-header bg-white d-flex flex-wrap align-items-center justify-content-between gap-3">
|
||
<strong class="mb-0">Date Selection</strong>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<select id="weekStartSelect" name="week_start" class="form-select form-select-sm" required>
|
||
<option value="">Select week</option>
|
||
<?php foreach ($sundayOptions as $sunday): ?>
|
||
<?php
|
||
try {
|
||
$startDt = new \DateTime($sunday);
|
||
$displayStart = $startDt->format('M d, Y');
|
||
} catch (\Exception $e) {
|
||
$displayStart = $sunday;
|
||
}
|
||
?>
|
||
<option value="<?= esc($sunday) ?>" <?= $sunday === $weekStartSelected ? 'selected' : '' ?>>
|
||
<?= esc($displayStart) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<div class="invalid-feedback">Week start is required.</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<input type="hidden" name="week_end" id="weekEndInput" value="<?= esc($weekEndValue) ?>" required>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row g-3 mt-1">
|
||
<?php
|
||
$subjectSections = $subjectSections ?? [];
|
||
$subjectCurriculum = $subjectCurriculum ?? [];
|
||
?>
|
||
<?php foreach ($subjectSections as $slug => $section): ?>
|
||
<?php
|
||
$unitValues = old("unit_$slug") ?? [];
|
||
$chapterValues = old("chapter_$slug") ?? [];
|
||
$rowsCount = max(count($unitValues), count($chapterValues));
|
||
?>
|
||
<div class="col-lg-6">
|
||
<div class="border border-dark rounded-3 p-3 h-100 subject-section">
|
||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||
<h4 class="mb-0"><?= esc($section['label'] ?? $slug) ?></h4>
|
||
</div>
|
||
<?php $curriculumOptions = $subjectCurriculum[$slug] ?? []; ?>
|
||
<?php
|
||
$preparedEntries = array_values(array_filter(array_map(function ($option) {
|
||
$chapterName = trim($option['chapter_name'] ?? '');
|
||
if ($chapterName === '') {
|
||
return null;
|
||
}
|
||
return [
|
||
'unit_number' => $option['unit_number'] ?? '',
|
||
'unit_title' => trim($option['unit_title'] ?? ''),
|
||
'chapter_name' => $chapterName,
|
||
];
|
||
}, $curriculumOptions)));
|
||
?>
|
||
<div class="mb-2 d-flex justify-content-between align-items-center">
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div class="position-relative">
|
||
<button type="button"
|
||
class="btn btn-sm btn-outline-dark"
|
||
data-add-unit-chapter
|
||
data-subject="<?= esc($slug) ?>">
|
||
<?= $slug === 'quran' ? '+ Add Surah, Arabic Subject' : '+ Add Unit, Chapter' ?>
|
||
</button>
|
||
<div class="subject-curriculum-list position-absolute d-none border rounded shadow-sm bg-white mt-1" id="curriculumList-<?= esc($slug) ?>" style="min-width: 220px; z-index: 5;">
|
||
<?php if (empty($preparedEntries)): ?>
|
||
<div class="p-2 text-muted small">No saved entries.</div>
|
||
<?php else: ?>
|
||
<?php foreach ($preparedEntries as $entry): ?>
|
||
<?php
|
||
$unitNumber = $entry['unit_number'] ?? '';
|
||
$unitTitle = $entry['unit_title'] ?? '';
|
||
$chapterName = $entry['chapter_name'] ?? '';
|
||
$displayParts = [];
|
||
if ($slug === 'islamic') {
|
||
if ($unitNumber) $displayParts[] = 'Unit ' . $unitNumber;
|
||
if ($unitTitle !== '') $displayParts[] = $unitTitle;
|
||
$prefix = $displayParts ? implode(' – ', $displayParts) . ' / ' : '';
|
||
$display = $prefix . $chapterName;
|
||
} else {
|
||
$display = 'Surah: ' . $chapterName;
|
||
}
|
||
?>
|
||
<button type="button"
|
||
class="dropdown-item text-start"
|
||
data-curriculum-entry
|
||
data-subject="<?= esc($slug) ?>"
|
||
data-unit-number="<?= esc($unitNumber) ?>"
|
||
data-unit-title="<?= esc($unitTitle) ?>"
|
||
data-chapter="<?= esc($chapterName) ?>">
|
||
<?= esc($display) ?>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
<?php if ($slug === 'quran'): ?>
|
||
<div class="px-2 py-2 border-top">
|
||
<div class="input-group input-group-sm">
|
||
<input type="text" class="form-control" placeholder="Custom Surah" data-custom-input data-subject="<?= esc($slug) ?>">
|
||
<button type="button" class="btn btn-outline-secondary" data-custom-entry data-subject="<?= esc($slug) ?>">Add</button>
|
||
</div>
|
||
<div class="form-text small text-muted">Add a custom Surah or Arabic target.</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="unit-chapter-rows mb-3" id="unitChapterRows-<?= esc($slug) ?>">
|
||
<?php for ($i = 0; $i < $rowsCount; $i++): ?>
|
||
<div class="row g-2 align-items-end mb-2 unit-chapter-entry">
|
||
<div class="col">
|
||
<input type="text" name="unit_<?= esc($slug) ?>[]" class="form-control form-control-sm" placeholder="Unit name" value="<?= esc($unitValues[$i] ?? '') ?>">
|
||
</div>
|
||
<div class="col">
|
||
<input type="text" name="chapter_<?= esc($slug) ?>[]" class="form-control form-control-sm" placeholder="Chapter" value="<?= esc($chapterValues[$i] ?? '') ?>">
|
||
</div>
|
||
</div>
|
||
<?php endfor; ?>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">What has been covered?</label>
|
||
<textarea name="covered_<?= esc($slug) ?>" class="form-control" rows="4" required placeholder="What was taught? Key topics, activities, memorization, etc."><?= esc(old("covered_$slug")) ?></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">Assigned homework:</label>
|
||
<textarea name="homework_<?= esc($slug) ?>" class="form-control" rows="3" placeholder="Homework, practice quizzes, review pages"><?= esc(old("homework_$slug")) ?></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">Attachment (optional):</label>
|
||
<input type="file" name="attachment_<?= esc($slug) ?>[]" class="form-control" accept=".pdf,.jpg,.jpeg,.png" multiple>
|
||
<div class="form-text small">Upload worksheets, quizzes, or reference files for <?= esc(strtolower($section['label'] ?? 'this subject')) ?>. You can select multiple files.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<div class="row mt-3">
|
||
<div class="col">
|
||
<div class="card shadow-sm">
|
||
<div class="card-body d-flex flex-column">
|
||
<button class="btn btn-primary w-100 mt-auto" type="submit" <?= $hasClass ? '' : 'disabled' ?>>Submit Progress</button>
|
||
<?php if (! $hasClass): ?>
|
||
<div class="text-muted small mt-2">
|
||
You are not assigned to a class. Contact the administrator to submit progress.
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="text-muted small mt-2">Make sure week dates and subject information are accurate before submitting.</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<?= $this->endSection() ?>
|
||
|
||
<?= $this->section('scripts') ?>
|
||
<script>
|
||
(() => {
|
||
'use strict';
|
||
const forms = document.querySelectorAll('.needs-validation');
|
||
Array.from(forms).forEach(form => {
|
||
form.addEventListener('submit', event => {
|
||
if (!form.checkValidity()) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
}
|
||
form.classList.add('was-validated');
|
||
}, false);
|
||
});
|
||
|
||
const weekStartSelect = document.getElementById('weekStartSelect');
|
||
const weekEndInput = document.getElementById('weekEndInput');
|
||
const updateWeekEnd = (value) => {
|
||
if (!weekEndInput) return;
|
||
if (!value) {
|
||
weekEndInput.value = '';
|
||
return;
|
||
}
|
||
const startDate = new Date(value);
|
||
if (Number.isNaN(startDate.valueOf())) {
|
||
weekEndInput.value = '';
|
||
return;
|
||
}
|
||
const endDate = new Date(startDate);
|
||
endDate.setDate(endDate.getDate() + 6);
|
||
weekEndInput.value = endDate.toISOString().slice(0, 10);
|
||
};
|
||
|
||
if (weekStartSelect) {
|
||
weekStartSelect.addEventListener('change', () => updateWeekEnd(weekStartSelect.value));
|
||
updateWeekEnd(weekStartSelect.value);
|
||
}
|
||
|
||
const buildRow = (slug, unitValue = '', chapterValue = '') => {
|
||
const row = document.createElement('div');
|
||
row.className = 'row g-2 align-items-end mb-2 unit-chapter-entry';
|
||
row.innerHTML = `
|
||
<div class="col">
|
||
<input type="text" name="unit_${slug}[]" class="form-control form-control-sm" placeholder="Unit name" />
|
||
</div>
|
||
<div class="col">
|
||
<input type="text" name="chapter_${slug}[]" class="form-control form-control-sm" placeholder="Chapter" />
|
||
</div>
|
||
`;
|
||
const inputs = row.querySelectorAll('input');
|
||
if (inputs[0]) {
|
||
inputs[0].value = unitValue;
|
||
}
|
||
if (inputs[1]) {
|
||
inputs[1].value = chapterValue;
|
||
}
|
||
return row;
|
||
};
|
||
|
||
const appendUnitChapterRow = (slug, unitValue = '', chapterValue = '') => {
|
||
const container = document.getElementById(`unitChapterRows-${slug}`);
|
||
if (!container) return;
|
||
container.appendChild(buildRow(slug, unitValue, chapterValue));
|
||
};
|
||
|
||
const buildUnitDisplay = (subject, unitNumber, unitTitle, { isQuran = false, isCustom = false } = {}) => {
|
||
const parts = [];
|
||
if (unitNumber) {
|
||
parts.push(`Unit ${unitNumber}`);
|
||
}
|
||
if (unitTitle) {
|
||
parts.push(unitTitle);
|
||
}
|
||
if (isQuran) {
|
||
return isCustom ? 'Custom' : 'Surah';
|
||
}
|
||
return parts.join(' – ');
|
||
};
|
||
|
||
const hideMenus = () => {
|
||
document.querySelectorAll('.subject-curriculum-list').forEach(menu => menu.classList.add('d-none'));
|
||
};
|
||
|
||
document.addEventListener('click', () => hideMenus());
|
||
|
||
document.querySelectorAll('[data-add-unit-chapter]').forEach(button => {
|
||
const subject = button.dataset.subject;
|
||
if (!subject) return;
|
||
const menu = document.getElementById(`curriculumList-${subject}`);
|
||
if (menu) {
|
||
menu.addEventListener('click', event => event.stopPropagation());
|
||
}
|
||
button.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
if (!menu) return;
|
||
const shouldShow = menu.classList.contains('d-none');
|
||
hideMenus();
|
||
if (shouldShow) {
|
||
menu.classList.remove('d-none');
|
||
activeMenus.add(menu);
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('[data-curriculum-entry]').forEach(entry => {
|
||
entry.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
const subject = entry.dataset.subject;
|
||
const unitNumber = entry.dataset.unitNumber || '';
|
||
const unitTitle = entry.dataset.unitTitle || '';
|
||
const chapterValue = entry.dataset.chapter || '';
|
||
if (!subject) return;
|
||
const unitValue = buildUnitDisplay(subject, unitNumber, unitTitle, { isQuran: subject === 'quran' });
|
||
appendUnitChapterRow(subject, unitValue, chapterValue);
|
||
hideMenus();
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('[data-custom-entry]').forEach(button => {
|
||
button.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
const subject = button.dataset.subject;
|
||
if (!subject) return;
|
||
const input = document.querySelector(`[data-custom-input][data-subject="${subject}"]`);
|
||
if (!input) return;
|
||
const customValue = input.value.trim();
|
||
if (customValue === '') return;
|
||
const unitValue = buildUnitDisplay(subject, '', '', { isQuran: subject === 'quran', isCustom: true });
|
||
appendUnitChapterRow(subject, unitValue, customValue);
|
||
input.value = '';
|
||
hideMenus();
|
||
});
|
||
});
|
||
})();
|
||
</script>
|
||
<?= $this->endSection() ?>
|