This commit is contained in:
Yasin İLKAYA 2025-12-21 01:10:18 +03:00
parent 324368f7df
commit 397ee75b2e
9 changed files with 454 additions and 13 deletions

View File

@ -24,13 +24,13 @@ Application.post("/catalog/list", MiddlewareAuth, express.urlencoded({extended:
*/
async function CatalogsList(request, response)
{
let start = request.body.start ?? 0;
let length = request.body.length ?? 100;
let term = request.body.search?.value ?? null;
let start = request.body?.start ?? 0;
let length = request.body?.length ?? 100;
let term = request.body?.search?.value ?? null;
let count = await countCatalogs(request.session.user_id, term);
let data = await getCatalogs(request.session.user_id,start,length, term);
response.json({
"draw": request.body.draw | 0,
"draw": request.body?.draw | 0,
"recordsTotal": count,
"recordsFiltered" : count,
"length": 0,

View File

@ -3,7 +3,7 @@ const Joi = require("joi");
const { PostDataProcess } = require("../core/postdata");
const User = require("../database/user");
const { MiddlewareAuth } = require("./auth");
const { createStudent, getStudents, countStudents, updateStudent, deleteStudent } = require("../database/student");
const { createStudent, getStudents, countStudents, updateStudent, deleteStudent, createEvent, getEvents, countEvents } = require("../database/student");
const express = require("express");
@ -182,4 +182,70 @@ function studentStoreValidation(body)
});
const {error} = schema.validate(body);
return error;
}
Application.get("/events", MiddlewareAuth, EventsPage);
/**
* @param {import("express").Request} request
* @param {import("express").Response} response
*/
async function EventsPage(request, response)
{
response.render("panel/studentevents");
}
Application.post("/event/store", MiddlewareAuth, PostDataProcess(), EventsStore);
/**
* @param {import("express").Request} request
* @param {import("express").Response} response
*/
async function EventsStore(request, response)
{
if(!request.body.student || !request.body.catalog)
{
return response.status(400).json({
status: "fail"
});
}
try{
await createEvent(
request.session.user_id,
request.body.student,
request.body.catalog
);
return response.status(200).json({
status: "success"
});
}catch(err){
console.log(err)
return response.status(500).json({
status: "fail"
});
}
}
Application.post("/events/list", MiddlewareAuth, express.urlencoded({extended: true}), EventsList);
/**
* @param {import("express").Request} request
* @param {import("express").Response} response
*/
async function EventsList(request, response)
{
let start = request.body.start ?? 0;
let length = request.body.length ?? 100;
let term = request.body.search?.value ?? null;
let count = await countEvents(request.session.user_id, term);
let data = await getEvents(request.session.user_id,start,length, term);
response.json({
"draw": request.body.draw | 0,
"recordsTotal": count,
"recordsFiltered" : count,
"data": data
});
}

View File

@ -8,6 +8,11 @@ exports.countStudents = countStudents;
exports.updateStudent = updateStudent;
exports.deleteStudent = deleteStudent;
exports.createEvent = createEvent;
exports.countEvents = countEvents;
exports.getEvents = getEvents;
async function createStudent(
owner_id,
@ -96,4 +101,53 @@ async function deleteStudent(owner_id, id)
.update({
deleted_at: DB.fn.now()
});
}
async function createEvent(owner_id, studentid, catalogid)
{
let student = await DB.table("students").where("owner_id",owner_id).where("id",studentid).whereNull("deleted_at").first();
let catalog = await DB.table("events").where("owner_id",owner_id).where("id",catalogid).whereNull("deleted_at").first();
if(student == null){
throw "Öğrenci yok"
}
if(catalog == null){
throw "Skor yok"
}
await DB.table("student_events").insert({
owner_id: owner_id,
student_id: student.id,
event_id: catalog.id,
score: catalog.score
});
}
async function countEvents()
{
return 0
}
async function getEvents(owner_id,start,length,searchTerm)
{
return await DB
.select([
"students.name as studentname",
"students.surname as studentsurname",
"student_events.score",
"events.name as catalog",
"student_events.created_at",
])
.table("student_events")
.innerJoin("students","students.id","=","student_id")
.innerJoin("events","events.id","=","event_id")
.where("student_events.owner_id",owner_id)
.where(function(q){
q.where("students.name","like",`%${searchTerm ?? ""}%`)
q.orWhere("events.name","like",`%${searchTerm ?? ""}%`)
})
.orderBy("student_events.created_at","desc")
.limit(length)
.offset(start);
}

View File

@ -124,6 +124,12 @@
data: "score",
name: "score"
},
{
title: "Tarih",
data: "created_at",
name: "created_at",
render: value => moment(value).format("DD.MM.YYYY HH:mm")
},
{
width: "1%",
title: "İşlemler",

View File

@ -0,0 +1,307 @@
<%-include("../partials/header.ejs") %>
<%-include("../partials/sidebar.ejs") %>
<div class="app-content">
<%-include("../partials/navbar.ejs") %>
<main>
<div class="container-fluid">
<!-- Breadcrumb start -->
<div class="row m-1">
<div class="col-12">
<h4 class="main-title">Öğrenci Skorları Geçmişi</h4>
<p>
Öğrencilere yeni değerler ekleyebilir ve silebilirsiniz
</p>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card ">
<div class="card-header ">
<div class="d-flex flex-row flex-1">
<h5 class="flex-fill">
Skor Geçmişi
</h5>
<div class="flex-min">
<button class="btn btn-success" data-bs-target="#add_event" data-bs-toggle="modal" type="button">
<i class="fa fa-plus"></i>
Skor Ekle
</button>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="app-datatable-default overflow-auto">
<table class="table display app-data-table default-data-table" id="eventslist"></table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<div aria-hidden="true" class="modal fade" id="add_event" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Yeni Skor Ekle</h5>
<button aria-label="Close" class="btn-close m-0 fs-5" data-bs-dismiss="modal" type="button"></button>
</div>
<form class="modal-body" id="eventsaveform" onsubmit="saveEvent(this);return false;">
<div class="row app-form">
<div class="col-md-6 mt-3">
<label class="form-label">Öğrenci</label>
<select name="student" class="form-control student" required></select>
</div>
<div class="col-md-6 mt-3">
<label class="form-label">Puan Kataloğu</label>
<select name="catalog" class="form-control catalog" required></select>
</div>
</div>
</form>
<div class="modal-footer">
<button class="btn btn-outline-success" type="submit" form="eventsaveform">Kaydet</button>
<button class="btn btn-light-secondary" data-bs-dismiss="modal" type="button">Kapat</button>
</div>
</div>
</div>
</div>
<script>
$(function(){
$('.catalog').select2({
placeholder: 'Puan kataloğunda ara',
minimumInputLength: 0,
allowClear: true,
dropdownParent: $('#add_event'),
ajax: {
url: '/catalog/list',
method: "post",
dataType: 'json',
delay: 250,
data: function (params) {
return {
start: 0,
length: 50,
search:{
value: params.term
}
};
},
processResults: function (data) {
return {
results: data.data.map(e => {
return {
id: e.id,
text: e.name + ` (+${e.score})`
}
})
};
}
}
});
$('.student').select2({
placeholder: 'Öğrencilerde ara',
minimumInputLength: 0,
allowClear: true,
dropdownParent: $('#add_event'),
ajax: {
url: '/students/list',
method: "post",
dataType: 'json',
delay: 250,
data: function (params) {
return {
start: 0,
length: 50,
search:{
value: params.term
}
};
},
processResults: function (data) {
return {
results: data.data.map(e => {
return {
id: e.id,
text: `${e.name} ${e.surname}`
}
})
};
}
}
});
})
</script>
<style>
.select2-container{
z-index: 10000;
}
</style>
<script>
let dataTable;
$(function(){
dataTable = $("#eventslist").DataTable({
serverSide: true,
processing: true,
autoWidth: false,
ajax: {
url: "/events/list",
method:"post"
},
columns: [
{
width: "1%",
title: "#",
data: null,
render: function (data, type, row, meta) {
return meta.row + 1;
}
},
{
title: "Öğrenci",
data: null,
name: "fullname",
render: function (data, row) {
return `${data.studentname} ${data.studentsurname || ''}`;
}
},
{
title: "Puan Kataloğu",
data: "catalog",
name: "catalog"
},
{
title: "Puan",
data: "score",
name: "score"
},
{
title: "Tarih",
data: "created_at",
name: "created_at",
render: value => moment(value).format("DD.MM.YYYY HH:mm")
},
{
width: "1%",
title: "İşlemler",
data: null,
orderable: false, // İşlemlere göre sıralama yapılamasın
render: function (data) {
return `
<div class="btn-group d-flex flex-row flex-nowrap" role="group">
<button class="btn btn-sm btn-outline-danger text-nowrap" onclick="deleteStudent(${data.id})" title="Sil">
<i class="fa fa-trash"></i>
Sil
</button>
</div>`;
}
}
],
"language": {
"url": "https://cdn.datatables.net/plug-ins/1.13.6/i18n/tr.json"
}
});
});
async function saveEvent(form)
{
blockui("#add_event .modal-content");
$.ajax({
url: "/event/store",
type: "post",
data: new FormData(form),
processData: false,
contentType: false,
success: function(response) {
dataTable.ajax.reload(null, false);
$("#add_event").modal("hide");
ublockui();
},
error: function(err) {
ublockui();
},
});
}
async function deleteStudent(id)
{
if(confirm("Kaydı silmek istediğinize emin misiniz?"))
{
$.ajax({
url: "/students/destroy",
type: "post",
data: {
id
},
success: function(response) {
dataTable.ajax.reload(null, false);
ublockui();
},
error: function(err) {
ublockui();
},
});
}
}
async function updateStudent(form)
{
blockui("#update_student .modal-content");
$.ajax({
url: "/students/update",
type: "post",
data: new FormData(form),
processData: false,
contentType: false,
success: function(response) {
dataTable.ajax.reload(null, false);
$("#update_student").modal("hide");
ublockui();
},
error: function(err) {
ublockui();
},
});
}
async function updateModal(tr)
{
let data = dataTable.row($(tr).closest('tr')).data();
$("#update_student form").get(0).reset();
$("#update_student [name='id']").val(data.id);
$("#update_student form input,#update_student form textarea").each(function(){
let name = this.name;
$(this).val(data[name]);
});
$("#update_student form select").each(function(){
let name = this.name;
$(this).find("option:selected").removeAttr("selected");
$(this).find(`option[value="${data[name]}"]`).attr("selected","selected");
});
$("#update_student").modal("show");
}
function blockui(ui)
{
$(blockui.id = ui).block({
message: '<div class="loader-container-box"><div class="loader"></div></div>',
//timeout: 13000,
overlayCSS: {
backgroundColor: 'rgba(var(--dark), 0.8)',
opacity: 0.8,
borderRadius: 'var(--app-border-radius)',
cursor: 'wait'
},
css: {
border: 0,
padding: 0,
backgroundColor: 'transparent'
}
});
}
function ublockui()
{
$(blockui.id).unblock()
}
</script>
<%-include("../partials/footer.ejs") %>

View File

@ -190,6 +190,12 @@
data: "email",
name: "email"
},
{
title: "Tarih",
data: "created_at",
name: "created_at",
render: value => moment(value).format("DD.MM.YYYY HH:mm")
},
{
width: "1%",
title: "İşlemler",

View File

@ -13,5 +13,7 @@
<script src="/assets/js/script.js"></script>
<script src="/assets/vendor/datatable/jquery.dataTables.min.js"></script>
<script src="/assets/vendor/block-ui/jquery.blockUI.js"></script>
<script src="/assets/vendor/select/select2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js"></script>
</body>
</html>

View File

@ -22,6 +22,7 @@
<link href="/assets/css/responsive.css" rel="stylesheet" type="text/css">
<script src="/assets/vendor/datatable/jquery-3.5.1.js"></script>
<link href="/assets/vendor/datatable/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
<link href="../assets/vendor/select/select2.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="app-wrapper">

View File

@ -44,7 +44,13 @@
<li class="menu-title">
<span>Panel</span>
</li>
<li class="no-sub">
<a href="/events">
<svg stroke="currentColor" stroke-width="1.5">
</svg>
Skor Verileri
</a>
</li>
<li class="no-sub">
<a href="/students">
<svg stroke="currentColor" stroke-width="1.5">
@ -59,13 +65,6 @@
Puan Katalogu
</a>
</li>
<!--li class="no-sub">
<a href="/catalogs">
<svg stroke="currentColor" stroke-width="1.5">
</svg>
Geçmiş İşlemler
</a>
</li-->
<li class="menu-title"><span>Hesap</span></li>
<li class="no-sub">
<a href="/profile">