Changes between Version 8 and Version 9 of UseCaseImplementationsFinal


Ignore:
Timestamp:
03/02/26 16:24:23 (3 days ago)
Author:
231067
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UseCaseImplementationsFinal

    v8 v9  
    217217Откако ќе додаде тема, ќе може да ја уреди, избрише или додели на некој студент, притоа студентот мора да стапил во контакт со менторот претходно на самата страна и да има договор помеѓу студентот и менторот за таа тема. Доколку темата е доделена, менторот може да ја одземе.
    218218
     219{{{
     220// POST: /Account/AddTopic
     221[HttpPost]
     222[ValidateAntiForgeryToken]
     223[Authorize]
     224public ActionResult AddTopic(TopicSuggestionCreateModel model)
     225{
     226    var currentUserId = User.Identity.GetUserId();
     227    var mentor = db.Users.OfType<Mentor>().FirstOrDefault(m => m.Id == currentUserId);
     228    if (mentor == null) return new HttpUnauthorizedResult();
     229
     230    if (!ModelState.IsValid)
     231    {
     232        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToArray();
     233        return Json(new { success = false, errors });
     234    }
     235
     236    var topic = new TopicSuggestion
     237    {
     238        MentorId = currentUserId,
     239        Title = model.Title,
     240        Description = model.Description,
     241        CreatedAt = DateTime.UtcNow
     242    };
     243
     244    db.TopicSuggestions.Add(topic);
     245    db.SaveChanges();
     246
     247    return Json(new
     248    {
     249        success = true,
     250        topic = new { topic.Id, topic.Title, topic.Description, topic.IsAssigned, topic.AssignedStudentId }
     251    });
     252}
     253
     254// POST: /Account/EditTopic
     255[HttpPost]
     256[ValidateAntiForgeryToken]
     257[Authorize]
     258public ActionResult EditTopic(int id, TopicSuggestionCreateModel model)
     259{
     260    var currentUserId = User.Identity.GetUserId();
     261    var topic = db.TopicSuggestions.Find(id);
     262    if (topic == null) return HttpNotFound();
     263    if (topic.MentorId != currentUserId) return new HttpUnauthorizedResult();
     264
     265    if (!ModelState.IsValid)
     266    {
     267        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToArray();
     268        return Json(new { success = false, errors });
     269    }
     270
     271    topic.Title = model.Title;
     272    topic.Description = model.Description;
     273    db.SaveChanges();
     274
     275    return Json(new { success = true });
     276}
     277
     278// POST: /Account/DeleteTopic
     279[HttpPost]
     280[ValidateAntiForgeryToken]
     281[Authorize]
     282public ActionResult DeleteTopic(int id)
     283{
     284    var currentUserId = User.Identity.GetUserId();
     285    var topic = db.TopicSuggestions.Find(id);
     286    if (topic == null) return HttpNotFound();
     287    if (topic.MentorId != currentUserId) return new HttpUnauthorizedResult();
     288
     289    if (topic.IsAssigned)
     290    {
     291        return Json(new { success = false, message = "Cannot delete an assigned topic." });
     292    }
     293
     294    db.TopicSuggestions.Remove(topic);
     295    db.SaveChanges();
     296
     297    return Json(new { success = true });
     298}
     299}}}
     300
    219301== Доделување теми на студент ==
    220302
     
    222304
    223305[[Image(доделитема.png)]]
     306
     307{{{
     308// POST: /Account/AssignTopic
     309[HttpPost]
     310[ValidateAntiForgeryToken]
     311[Authorize]
     312public async Task<ActionResult> AssignTopic(int topicId, string studentId)
     313{
     314    var currentUserId = User.Identity.GetUserId();
     315    var topic = db.TopicSuggestions.Include(t => t.Mentor).FirstOrDefault(t => t.Id == topicId);
     316    if (topic == null) return HttpNotFound();
     317    if (topic.MentorId != currentUserId) return new HttpUnauthorizedResult();
     318    if (topic.IsAssigned) return Json(new { success = false, message = "Topic already assigned." });
     319
     320    var student = db.Users.OfType<Student>().FirstOrDefault(s => s.Id == studentId);
     321    if (student == null) return Json(new { success = false, message = "Student not found." });
     322
     323    topic.IsAssigned = true;
     324    topic.AssignedStudentId = studentId;
     325    topic.AssignedAt = DateTime.UtcNow;
     326    db.SaveChanges();
     327
     328    // create an on-site message to student so it shows in their notifications/inbox
     329    var msg = new Message
     330    {
     331        FromUserId = currentUserId,
     332        ToUserId = studentId,
     333        Subject = $"Ви е доделенa тема: {topic.Title}",
     334        Body = $"Ви е доделена тема од менторот {topic.Mentor.Name} {topic.Mentor.Surname}: {topic.Title}\n\n{topic.Description}",
     335        Timestamp = DateTime.UtcNow,
     336        IsRead = false
     337    };
     338    db.Messages.Add(msg);
     339    db.SaveChanges();
     340
     341    // Email the student (best-effort)
     342    try
     343    {
     344        if (!string.IsNullOrWhiteSpace(student.Email))
     345        {
     346            var subject = $"Доделена ви е тема: {topic.Title}";
     347            var body = $@"
     348        <p>Почитуван/а {HttpUtility.HtmlEncode(student.Name)} {HttpUtility.HtmlEncode(student.Surname)},</p>
     349        <p>Менторот <strong>{HttpUtility.HtmlEncode(topic.Mentor.Name)} {HttpUtility.HtmlEncode(topic.Mentor.Surname)}</strong> ви додели тема:</p>
     350        <h4>{HttpUtility.HtmlEncode(topic.Title)}</h4>
     351        <p>{HttpUtility.HtmlEncode(topic.Description)}</p>
     352        <hr/><p>Ова е автоматска порака.</p>";
     353            await _emailService.SendEmailAsync(student.Email, subject, body);
     354        }
     355    }
     356    catch (Exception ex)
     357    {
     358        System.Diagnostics.Debug.WriteLine("Email send failed (AssignTopic): " + ex);
     359    }
     360
     361    return Json(new { success = true });
     362}
     363
     364// POST: /Account/UnassignTopic
     365[HttpPost]
     366[ValidateAntiForgeryToken]
     367[Authorize]
     368public async Task<ActionResult> UnassignTopic(int topicId)
     369{
     370    var currentUserId = User.Identity.GetUserId();
     371    var topic = db.TopicSuggestions.Include(t => t.Mentor).Include(t => t.AssignedStudent).FirstOrDefault(t => t.Id == topicId);
     372    if (topic == null) return HttpNotFound();
     373    if (topic.MentorId != currentUserId) return new HttpUnauthorizedResult();
     374    if (!topic.IsAssigned) return Json(new { success = false, message = "Topic not assigned." });
     375
     376    var student = topic.AssignedStudent;
     377    topic.IsAssigned = false;
     378    topic.AssignedStudentId = null;
     379    topic.AssignedAt = null;
     380    db.SaveChanges();
     381
     382    // notify student with message
     383    if (student != null)
     384    {
     385        var msg = new Message
     386        {
     387            FromUserId = currentUserId,
     388            ToUserId = student.Id,
     389            Subject = $"Тема {topic.Title} е оневозможена",
     390            Body = $"Менторот {topic.Mentor.Name} {topic.Mentor.Surname} ја оневозможи или одзеде темата {topic.Title}.",
     391            Timestamp = DateTime.UtcNow,
     392            IsRead = false
     393        };
     394        db.Messages.Add(msg);
     395        db.SaveChanges();
     396
     397        try
     398        {
     399            if (!string.IsNullOrWhiteSpace(student.Email))
     400            {
     401                var subject = $"Тема {topic.Title} е одземена/оневозможена";
     402                var body = $@"
     403            <p>Почитуван/а {HttpUtility.HtmlEncode(student.Name)} {HttpUtility.HtmlEncode(student.Surname)},</p>
     404            <p>Менторот <strong>{HttpUtility.HtmlEncode(topic.Mentor.Name)} {HttpUtility.HtmlEncode(topic.Mentor.Surname)}</strong> ја одзеде темата <strong>{HttpUtility.HtmlEncode(topic.Title)}</strong>.</p>
     405            <hr/><p>Ова е автоматска порака.</p>";
     406                await _emailService.SendEmailAsync(student.Email, subject, body);
     407            }
     408        }
     409        catch (Exception ex)
     410        {
     411            System.Diagnostics.Debug.WriteLine("Email send failed (UnassignTopic): " + ex);
     412        }
     413    }
     414
     415    return Json(new { success = true });
     416}
     417}}}
    224418
    225419Секој корисник може да ги види предлог темите на менторот на неговиот профил. Може да види наслов, опис, доколку се доделени или не. Ако е менторот, или пак студентот на кој е доделена темата, тогаш има посебно поле „Доделена на студент:“
     
    228422[[Image(темипрофил2.png)]]
    229423
     424{{{
     425// GET: /Account/GetMentorTopics (returns JSON list of available topics for a mentor)
     426[Authorize]
     427public JsonResult GetMentorTopics(string mentorId)
     428{
     429    var topics = db.TopicSuggestions
     430                   .Where(t => t.MentorId == mentorId && !t.IsAssigned)
     431                   .OrderByDescending(t => t.CreatedAt)
     432                   .Select(t => new { t.Id, t.Title, t.Description })
     433                   .ToList();
     434
     435    return Json(new { success = true, topics }, JsonRequestBehavior.AllowGet);
     436}
     437
     438[Authorize]
     439public JsonResult GetTopicCandidates(int topicId)
     440{
     441    var topic = db.TopicSuggestions.Find(topicId);
     442    if (topic == null) return Json(new { success = false, message = "Topic not found" }, JsonRequestBehavior.AllowGet);
     443
     444    // candidates: students who contacted this mentor and optionally selected this topic, fallback to all students who contacted
     445    var candidates = db.MentorContacts
     446        .Where(c => c.MentorId == topic.MentorId)
     447        .Include(c => c.Student)
     448        .GroupBy(c => c.StudentId)
     449        .Select(g => new
     450        {
     451            id = g.Key,
     452            name = g.Select(x => x.Student.Name + " " + x.Student.Surname).FirstOrDefault()
     453        })
     454        .Where(x => x.id != null)
     455        .ToList();
     456
     457    // ensure distinct and non-null
     458    candidates = candidates.GroupBy(x => x.id).Select(g => g.First()).ToList();
     459
     460    return Json(new { success = true, candidates }, JsonRequestBehavior.AllowGet);
     461}
     462}}}
     463
    230464= Студент =
    231465