Compare commits
No commits in common. "30c3fbcadc472d94d007efae23bf6b59e134e678" and "c3c09f89669b2e5b3604730b316427ace63a8aa1" have entirely different histories.
30c3fbcadc
...
c3c09f8966
|
@ -28,12 +28,6 @@ namespace FIT5032_Assignment {
|
||||||
url: "Appointments",
|
url: "Appointments",
|
||||||
defaults: new { controller = "Appointments", action = "Index", id = UrlParameter.Optional }
|
defaults: new { controller = "Appointments", action = "Index", id = UrlParameter.Optional }
|
||||||
);
|
);
|
||||||
|
|
||||||
routes.MapRoute(
|
|
||||||
name: "System",
|
|
||||||
url: "System/{action}/{id}",
|
|
||||||
defaults: new { controller = "System", action = "GetUploadedImage", id = UrlParameter.Optional }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,24 +16,9 @@ using Org.BouncyCastle.Security;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using RestSharp.Authenticators;
|
|
||||||
using RestSharp;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace FIT5032_Assignment.Controllers {
|
namespace FIT5032_Assignment.Controllers {
|
||||||
public class AppointmentsController : Controller {
|
public class AppointmentsController : Controller {
|
||||||
public class PassageUserAPI {
|
|
||||||
public PassageUserEntity User { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PassageUserEntity {
|
|
||||||
public string CreatedAt { get; set; }
|
|
||||||
public string Email { get; set; }
|
|
||||||
public bool EmailVerified { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private Database1Entities db = new Database1Entities();
|
private Database1Entities db = new Database1Entities();
|
||||||
|
|
||||||
// Login check
|
// Login check
|
||||||
|
@ -108,142 +93,13 @@ namespace FIT5032_Assignment.Controllers {
|
||||||
|
|
||||||
// GET: Appointments
|
// GET: Appointments
|
||||||
public ActionResult Index() {
|
public ActionResult Index() {
|
||||||
// Check login
|
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
// Detect user role
|
|
||||||
ViewBag.role = db.Users.Find(userProfile.uuid).role;
|
|
||||||
|
|
||||||
var appointments = new List<Tuple<Appointments, Users>>();
|
|
||||||
if (userProfile.role == 1) { // patient
|
|
||||||
var dbData = db.Appointments.Where(a => a.patient == userProfile.uuid).OrderByDescending(a => a.createdAt).ToList();
|
|
||||||
foreach (var item in dbData) {
|
|
||||||
Trace.WriteLine(item.uuid);
|
|
||||||
appointments.Add(new Tuple<Appointments, Users>(item, db.Users.Find(item.responsibleBy)));
|
|
||||||
}
|
|
||||||
} else if (userProfile.role == 2) { // doctor
|
|
||||||
var dbData = db.Appointments.Where(a => a.responsibleBy == userProfile.uuid).OrderByDescending(a => a.createdAt).ToList();
|
|
||||||
foreach (var item in dbData) {
|
|
||||||
Trace.WriteLine(item.uuid);
|
|
||||||
appointments.Add(new Tuple<Appointments, Users>(item, db.Users.Find(item.patient)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ViewBag.appointments = appointments;
|
|
||||||
ViewBag.tip = TempData["tip"];
|
ViewBag.tip = TempData["tip"];
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Appointments/Cancel/uuid
|
// GET: Appointments/Details/5
|
||||||
public ActionResult Cancel(string id) {
|
public ActionResult Details(int id) {
|
||||||
// Check login
|
return View();
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the appointment is belong to the doctor or patient
|
|
||||||
var appointment = db.Appointments.Find(id);
|
|
||||||
if (appointment == null) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.patient != userProfile.uuid && appointment.responsibleBy != userProfile.uuid) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check status == 0
|
|
||||||
if (appointment.status != 0) {
|
|
||||||
TempData["tip"] = "Operation invalid";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status
|
|
||||||
appointment.status = -1;
|
|
||||||
db.Entry(appointment).State = EntityState.Modified;
|
|
||||||
db.SaveChanges();
|
|
||||||
|
|
||||||
TempData["tip"] = "The appointment has been cancelled.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionResult Approve(string id) {
|
|
||||||
// Check login
|
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
// Detect user role
|
|
||||||
ViewBag.role = db.Users.Find(userProfile.uuid).role;
|
|
||||||
|
|
||||||
// Only doctor can approve appointment
|
|
||||||
if (userProfile.role != 2) {
|
|
||||||
TempData["tip"] = "This operation is not allowed.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the appointment is belong to the doctor or patient
|
|
||||||
var appointment = db.Appointments.Find(id);
|
|
||||||
if (appointment == null) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.responsibleBy != userProfile.uuid) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check status == 0
|
|
||||||
if (appointment.status != 0) {
|
|
||||||
TempData["tip"] = "Operation invalid";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status
|
|
||||||
appointment.status = 1;
|
|
||||||
db.Entry(appointment).State = EntityState.Modified;
|
|
||||||
db.SaveChanges();
|
|
||||||
|
|
||||||
TempData["tip"] = "The appointment has been approved.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Appointments/Create
|
// GET: Appointments/Create
|
||||||
|
@ -346,227 +202,40 @@ namespace FIT5032_Assignment.Controllers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Appointments/UploadImage/uuid
|
// GET: Appointments/Edit/5
|
||||||
public ActionResult UploadImage(string id) {
|
public ActionResult Edit(int id) {
|
||||||
// Check login
|
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
// Detect user role
|
|
||||||
ViewBag.role = db.Users.Find(userProfile.uuid).role;
|
|
||||||
if (userProfile.role != 2) {
|
|
||||||
TempData["tip"] = "This operation is not allowed.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the appointment is belong to the doctor
|
|
||||||
var appointment = db.Appointments.Find(id);
|
|
||||||
if (appointment == null) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.responsibleBy != userProfile.uuid) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check status == 1
|
|
||||||
if (appointment.status != 1) {
|
|
||||||
TempData["tip"] = "Operation invalid";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewBag.appointment = appointment;
|
|
||||||
ViewBag.patient = db.Users.Find(appointment.patient);
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST: Appointments/Edit/5
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult> UploadImage(HttpPostedFileBase image, string appointmentUuid) {
|
public ActionResult Edit(int id, FormCollection collection) {
|
||||||
try {
|
try {
|
||||||
// Check login
|
// TODO: Add update logic here
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
// Detect user role
|
|
||||||
ViewBag.role = db.Users.Find(userProfile.uuid).role;
|
|
||||||
if (userProfile.role != 2) {
|
|
||||||
TempData["tip"] = "This operation is not allowed.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the appointment exist & status == 1 & responsibleBy == doctor
|
return RedirectToAction("Index");
|
||||||
var appointment = db.Appointments.Find(appointmentUuid);
|
}
|
||||||
if (appointment == null) {
|
catch {
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
return View();
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.responsibleBy != userProfile.uuid) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.status != 1) {
|
|
||||||
TempData["tip"] = "Operation invalid";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// check uploaded file
|
|
||||||
if (image == null) {
|
|
||||||
ViewBag.tip = "Please upload a file";
|
|
||||||
ViewBag.appointment = appointment;
|
|
||||||
ViewBag.patient = db.Users.Find(appointment.patient);
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check format: png, jpg, jpeg
|
|
||||||
string[] formats = new string[] { ".png", ".jpg", ".jpeg" };
|
|
||||||
string extension = Path.GetExtension(image.FileName);
|
|
||||||
if (!formats.Contains(extension)) {
|
|
||||||
ViewBag.tip = "Please upload a png, jpg or jpeg file";
|
|
||||||
ViewBag.appointment = appointment;
|
|
||||||
ViewBag.patient = db.Users.Find(appointment.patient);
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
|
|
||||||
// save file
|
|
||||||
var fileId = Guid.NewGuid().ToString();
|
|
||||||
var fileName = fileId + extension;
|
|
||||||
var filePath = Path.Combine(Server.MapPath("~/App_Data/upload_images"), fileName);
|
|
||||||
image.SaveAs(filePath);
|
|
||||||
|
|
||||||
// Create image entity to database
|
|
||||||
var appointmentId = appointment.uuid;
|
|
||||||
var imageId = Guid.NewGuid().ToString();
|
|
||||||
var patientUuid = appointment.patient;
|
|
||||||
var dbImage = new Images {
|
|
||||||
uuid = imageId,
|
|
||||||
appointment = appointmentId,
|
|
||||||
patient = patientUuid,
|
|
||||||
responsibleBy = userProfile.uuid,
|
|
||||||
createdAt = DateTime.Now,
|
|
||||||
file = fileName,
|
|
||||||
status = 0,
|
|
||||||
};
|
|
||||||
db.Images.Add(dbImage);
|
|
||||||
// Change appointment status to 2
|
|
||||||
appointment.status = 2;
|
|
||||||
db.Entry(appointment).State = EntityState.Modified;
|
|
||||||
db.SaveChanges();
|
|
||||||
|
|
||||||
// Find patient email from Passage service
|
|
||||||
var credential = db.Credentials.Where(res => (res.user == patientUuid) && (res.provider == 0));
|
|
||||||
Trace.WriteLine(credential.First().uniqueIdCode);
|
|
||||||
var user_id = credential.First().uniqueIdCode;
|
|
||||||
var app_id = "ZHM5whW5xsZEczTn2loffzjN";
|
|
||||||
RestClient passageClient = new RestClient(new RestClientOptions($"https://api.passage.id/v1/apps/{app_id}"));
|
|
||||||
passageClient.AddDefaultHeader("Authorization", "Bearer vF4ch1wUf8.1cqOms9JMmUbqMGohlkJLzGDVlbF51D03fJnLfxwkn8kyAaVVjfvySufW9vXb3p3");
|
|
||||||
var psgRequest = new RestRequest($"users/{user_id}", Method.Get);
|
|
||||||
|
|
||||||
// Send request
|
|
||||||
var passageResponse = await passageClient.ExecuteAsync(psgRequest);
|
|
||||||
Trace.WriteLine(passageResponse.Content);
|
|
||||||
|
|
||||||
// Transfer response
|
|
||||||
var passageResponseJson = JsonConvert.DeserializeObject<PassageUserAPI>(passageResponse.Content);
|
|
||||||
var patientEmail = passageResponseJson.User.Email;
|
|
||||||
|
|
||||||
// Send attached email with mailgun
|
|
||||||
var doctorName = userProfile.displayName;
|
|
||||||
var patient = db.Users.Find(patientUuid);
|
|
||||||
RestClient client = new RestClient(new RestClientOptions("https://api.mailgun.net/v3/test.astrian.moe") {
|
|
||||||
Authenticator = new HttpBasicAuthenticator("api", "365900a7818241eafcbbf82e59cf99e8-5465e583-b4966e64"),
|
|
||||||
});
|
|
||||||
var request = new RestRequest("messages", Method.Post);
|
|
||||||
request.AddParameter("from", "Xpectrum <xpectrum@test.astrian.moe>");
|
|
||||||
request.AddParameter("to", patientEmail);
|
|
||||||
request.AddParameter("subject", "Xpectrum: New image available");
|
|
||||||
request.AddParameter("text", $"Hi {patient.displayName},\n\nDr. {doctorName} has uploaded a new image for you.\n\nPlease check the attachment.\n\nBest regards,\nXpectrum");
|
|
||||||
request.AddFile("attachment", filePath);
|
|
||||||
|
|
||||||
// Send request
|
|
||||||
var response = await client.ExecuteAsync(request);
|
|
||||||
Trace.WriteLine(response.Content);
|
|
||||||
|
|
||||||
TempData["tip"] = "The image has been attached to the appointment.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
} catch {
|
|
||||||
TempData["tip"] = "System error";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Detail(string id) {
|
// GET: Appointments/Delete/5
|
||||||
// Verify login
|
public ActionResult Delete(int id) {
|
||||||
if (Request.Cookies["psg_auth_token"] == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var user = psgCredentialVerify(Request.Cookies["psg_auth_token"].Value);
|
|
||||||
if (user == null) {
|
|
||||||
// Redirect to home page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
var userProfile = loginInfo(user);
|
|
||||||
if (userProfile == null) {
|
|
||||||
// Redirect to home page, and remove cookies
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect user role
|
|
||||||
ViewBag.role = db.Users.Find(userProfile.uuid).role;
|
|
||||||
|
|
||||||
// Check if the appointment is belong to the doctor or patient
|
|
||||||
var appointment = db.Appointments.Find(id);
|
|
||||||
if (appointment == null) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
if (appointment.patient != userProfile.uuid && appointment.responsibleBy != userProfile.uuid) {
|
|
||||||
TempData["tip"] = "The appointment does not exist.";
|
|
||||||
return Redirect("/Appointments/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewBag.appointment = appointment;
|
|
||||||
|
|
||||||
// Fetch doctor profile
|
|
||||||
ViewBag.doctor = db.Doctors.Where(d => d.user == appointment.responsibleBy);
|
|
||||||
ViewBag.doctorUser = db.Users.Find(appointment.responsibleBy);
|
|
||||||
|
|
||||||
// Fetch patient profile
|
|
||||||
ViewBag.patient = db.Users.Find(appointment.patient);
|
|
||||||
|
|
||||||
// Fetch images
|
|
||||||
var image = db.Images.Where(i => i.appointment == id).First();
|
|
||||||
ViewBag.image = image;
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST: Appointments/Delete/5
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult Delete(int id, FormCollection collection) {
|
||||||
|
try {
|
||||||
|
// TODO: Add delete logic here
|
||||||
|
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ namespace FIT5032_Assignment.Controllers {
|
||||||
public DbSet<Patients> Patients { get; set; }
|
public DbSet<Patients> Patients { get; set; }
|
||||||
public DbSet<Doctors> Doctors { get; set; }
|
public DbSet<Doctors> Doctors { get; set; }
|
||||||
public DbSet<Appointments> Appointments { get; set; }
|
public DbSet<Appointments> Appointments { get; set; }
|
||||||
public DbSet<Images> Images { get; set; }
|
|
||||||
}
|
}
|
||||||
public class HomeController : Controller {
|
public class HomeController : Controller {
|
||||||
public static string GetMd5Hash(string input) {
|
public static string GetMd5Hash(string input) {
|
||||||
|
@ -169,10 +168,6 @@ namespace FIT5032_Assignment.Controllers {
|
||||||
ViewBag.role = dbUser.First().role == 1 ? "Patient" : "Doctor";
|
ViewBag.role = dbUser.First().role == 1 ? "Patient" : "Doctor";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Remove cookies and refresh page
|
|
||||||
Response.Cookies["psg_auth_token"].Expires = DateTime.Now.AddDays(-1);
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return View();
|
return View();
|
||||||
|
@ -412,8 +407,6 @@ namespace FIT5032_Assignment.Controllers {
|
||||||
return new HttpStatusCodeResult(HttpStatusCode.BadGateway);
|
return new HttpStatusCodeResult(HttpStatusCode.BadGateway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.Mvc;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace FIT5032_Assignment.Controllers {
|
|
||||||
public class SystemController : Controller {
|
|
||||||
// GET: System
|
|
||||||
public ActionResult GetUploadedImage(string fileName) {
|
|
||||||
var filePath = Server.MapPath("~/App_Data/upload_images/" + fileName);
|
|
||||||
if (!System.IO.File.Exists(filePath)) {
|
|
||||||
return HttpNotFound();
|
|
||||||
}
|
|
||||||
var fileContent = System.IO.File.ReadAllText(filePath);
|
|
||||||
var contentType = MimeMapping.GetMimeMapping(fileName);
|
|
||||||
return File(fileContent, contentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -186,7 +186,6 @@
|
||||||
<Compile Include="App_Start\RouteConfig.cs" />
|
<Compile Include="App_Start\RouteConfig.cs" />
|
||||||
<Compile Include="Controllers\AppointmentsController.cs" />
|
<Compile Include="Controllers\AppointmentsController.cs" />
|
||||||
<Compile Include="Controllers\HomeController.cs" />
|
<Compile Include="Controllers\HomeController.cs" />
|
||||||
<Compile Include="Controllers\System.cs" />
|
|
||||||
<Compile Include="Global.asax.cs">
|
<Compile Include="Global.asax.cs">
|
||||||
<DependentUpon>Global.asax</DependentUpon>
|
<DependentUpon>Global.asax</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -323,13 +322,10 @@
|
||||||
<Content Include="Views\Home\ImageUpload.cshtml" />
|
<Content Include="Views\Home\ImageUpload.cshtml" />
|
||||||
<Content Include="Views\Appointments\Index.cshtml" />
|
<Content Include="Views\Appointments\Index.cshtml" />
|
||||||
<Content Include="Views\Appointments\Create.cshtml" />
|
<Content Include="Views\Appointments\Create.cshtml" />
|
||||||
<Content Include="Views\Appointments\UploadImage.cshtml" />
|
<Content Include="Views\Appointments\CreateByDoctor.cshtml" />
|
||||||
<Content Include="Views\Appointments\Detail.cshtml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="App_Data\upload_images\" />
|
|
||||||
<Folder Include="Views\Default\" />
|
<Folder Include="Views\Default\" />
|
||||||
<Folder Include="Views\System\" />
|
|
||||||
<Folder Include="Views\Test\" />
|
<Folder Include="Views\Test\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<IISExpressUseClassicPipelineMode />
|
<IISExpressUseClassicPipelineMode />
|
||||||
<UseGlobalApplicationHostFile />
|
<UseGlobalApplicationHostFile />
|
||||||
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
|
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
|
||||||
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
<Controller_SelectedScaffolderID>MvcControllerWithActionsScaffolder</Controller_SelectedScaffolderID>
|
||||||
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
|
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
|
||||||
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
|
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
|
||||||
<WebStackScaffolding_LayoutPageFile>~/Views/Shared/_Layout.cshtml</WebStackScaffolding_LayoutPageFile>
|
<WebStackScaffolding_LayoutPageFile>~/Views/Shared/_Layout.cshtml</WebStackScaffolding_LayoutPageFile>
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
|
|
||||||
@{
|
|
||||||
ViewBag.Title = "Detail";
|
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h2>Appointment detail</h2>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="field-title">Appointment date</div>
|
|
||||||
<div class="field-content field-content-user">@ViewBag.appointment.appointmentDate</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="field-title">Doctor</div>
|
|
||||||
<div class="field-content field-content-user">
|
|
||||||
<img src="@ViewBag.doctorUser.avatar" />
|
|
||||||
<span>@ViewBag.doctorUser.displayName</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="field-title">Patient</div>
|
|
||||||
<div class="field-content field-content-user">
|
|
||||||
<img src="@ViewBag.patient.avatar" />
|
|
||||||
<span>@ViewBag.patient.displayName</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="field-title">Status</div>
|
|
||||||
<div class="field-content">
|
|
||||||
@if(ViewBag.appointment.status == 0) {
|
|
||||||
<span class="badge badge-warning">Pending</span>
|
|
||||||
} else if(ViewBag.appointment.status == 1) {
|
|
||||||
<span class="badge badge-info">Waiting for serve</span>
|
|
||||||
} else if(ViewBag.appointment.status == -1) {
|
|
||||||
<span class="badge badge-secondary">Cancelled</span>
|
|
||||||
} else if(ViewBag.appointment.status == 2) {
|
|
||||||
<span class="badge badge-info">Completed</span>
|
|
||||||
} else {
|
|
||||||
<span class="badge badge-secondary">Unknown</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if(ViewBag.appointment.status == 2) {
|
|
||||||
<div class="field">
|
|
||||||
<div class="field-title">Attached image</div>
|
|
||||||
<div class="field-content">
|
|
||||||
<img src="/System/GetUploadedImage?fileName=@ViewBag.image.file" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<style>
|
|
||||||
.field {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.field .field-title {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
.field .field-content {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
.field .field-content-user {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.field .field-content-user img {
|
|
||||||
width: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-warning {
|
|
||||||
background-color: #ffc107;
|
|
||||||
border-color: #ffc107;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-success {
|
|
||||||
background-color: #28a745;
|
|
||||||
border-color: #28a745;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-danger {
|
|
||||||
background-color: #dc3545;
|
|
||||||
border-color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-info {
|
|
||||||
background-color: #17a2b8;
|
|
||||||
border-color: #17a2b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-secondary {
|
|
||||||
background-color: #6c757d;
|
|
||||||
border-color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userprofile .displaname {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userprofile .avatar {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewBag.Title = "Appointments";
|
ViewBag.Title = "Appointments";
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (ViewBag.tip != null) {
|
@if (ViewBag.tip != null) {
|
||||||
|
@ -10,141 +10,8 @@
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="titlebar">
|
<h2>Appointments</h2>
|
||||||
<h2>My appointments</h2>
|
|
||||||
@if (ViewBag.role == 1) {<a href="./Create" class="btn btn-primary">Make a new appointment</a>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (ViewBag.role == 1) {
|
<ul>
|
||||||
<table class="table table-hover">
|
<li><a href="./Create">Make a new appointment</a></li>
|
||||||
<tr>
|
</ul>
|
||||||
<th>Doctor</th>
|
|
||||||
<th>Appointment date</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
@foreach (var item in ViewBag.appointments) {
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="userprofile">
|
|
||||||
<img src='@item.Item2.avatar' class="avatar" />
|
|
||||||
<span class="displaname">@item.Item2.displayName</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>@item.Item1.appointmentDate</td>
|
|
||||||
<td>
|
|
||||||
@if (item.Item1.status == 0) {
|
|
||||||
<span class="badge badge-warning">Pending</span>
|
|
||||||
} else if (item.Item1.status == 1) {
|
|
||||||
<span class="badge badge-info">Waiting for serve</span>
|
|
||||||
} else if (item.Item1.status == -1) {
|
|
||||||
<span class="badge badge-secondary">Cancelled</span>
|
|
||||||
} else if (item.Item1.status == 2) {
|
|
||||||
<span class="badge badge-info">Completed</span>
|
|
||||||
} else {
|
|
||||||
<span class="badge badge-secondary">Unknown</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if (item.Item1.status == 0) {
|
|
||||||
<a href='./Cancel/@item.Item1.uuid' class="btn btn-sm btn-danger">Cancel</a>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
} else if (ViewBag.role == 2) {
|
|
||||||
<table class="table table-hover">
|
|
||||||
<tr>
|
|
||||||
<th>Patient</th>
|
|
||||||
<th>Appointment date</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
@foreach (var item in ViewBag.appointments) {
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="userprofile">
|
|
||||||
<img src='@item.Item2.avatar' class="avatar" />
|
|
||||||
<span class="displaname">@item.Item2.displayName</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>@item.Item1.appointmentDate</td>
|
|
||||||
<td>
|
|
||||||
@if (item.Item1.status == 0) {
|
|
||||||
<span class="badge badge-warning">Pending</span>
|
|
||||||
} else if (item.Item1.status == 1) {
|
|
||||||
<span class="badge badge-info">Waiting for serve</span>
|
|
||||||
} else if (item.Item1.status == -1) {
|
|
||||||
<span class="badge badge-secondary">Cancelled</span>
|
|
||||||
} else if (item.Item1.status == 2) {
|
|
||||||
<span class="badge badge-info">Completed</span>
|
|
||||||
} else {
|
|
||||||
<span class="badge badge-secondary">Unknown</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if (item.Item1.status == 0) {
|
|
||||||
<a href='./Approve/@item.Item1.uuid' class="btn btn-sm btn-primary">Approve</a>
|
|
||||||
<a href='./Cancel/@item.Item1.uuid' class="btn btn-sm btn-danger">Cancel</a>
|
|
||||||
} else if (item.Item1.status == 1) {
|
|
||||||
<a href="./UploadImage/@item.Item1.uuid" class="btn btn-sm btn-primary">Upload Image</a>
|
|
||||||
} else if (item.Item1.status == 2) {
|
|
||||||
<a href="./Detail/@item.Item1.uuid" class="btn btn-sm btn-primary">Detail</a>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<style>
|
|
||||||
.titlebar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-warning {
|
|
||||||
background-color: #ffc107;
|
|
||||||
border-color: #ffc107;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-success {
|
|
||||||
background-color: #28a745;
|
|
||||||
border-color: #28a745;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-danger {
|
|
||||||
background-color: #dc3545;
|
|
||||||
border-color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-info {
|
|
||||||
background-color: #17a2b8;
|
|
||||||
border-color: #17a2b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-secondary {
|
|
||||||
background-color: #6c757d;
|
|
||||||
border-color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userprofile .displaname {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userprofile .avatar {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
@model FIT5032_Assignment.Models.ImageUploadForm
|
|
||||||
@{
|
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (ViewBag.tip != null) {
|
|
||||||
<div class="alert alert-success" role="alert">
|
|
||||||
@ViewBag.tip
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h2>Upload image</h2>
|
|
||||||
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
|
||||||
<input type="hidden" name="appointmentUuid" value="@ViewBag.appointment.uuid" />
|
|
||||||
<div style="margin-bottom: 20px;">You are about to upload the image for the appointment booked by <b>@ViewBag.patient.displayName</b> in <b>@ViewBag.appointment.appointmentDate</b></div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="image">Select the image</label>
|
|
||||||
<div class='input-group'>
|
|
||||||
<input type="file" class="form-control-file" id="image" name="image" accept="image/png, image/jpeg, image/jpg" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary" style="margin-top: 20px;">Submit</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
@Scripts.Render("~/bundles/jqueryval")
|
|
||||||
}
|
|
|
@ -4,11 +4,38 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<h2>Upload image</h2>
|
@using (Html.BeginForm("ImageUpload", "HomeController", FormMethod.Post, new { enctype = "multipart/form-data" }))
|
||||||
|
{
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<h4>Upload Image</h4>
|
||||||
|
<hr />
|
||||||
|
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
|
||||||
|
<div class="form-group">
|
||||||
|
@Html.LabelFor(model => model.patientEmail, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||||
|
<div class="col-md-10">
|
||||||
|
@Html.EditorFor(model => model.patientEmail, new { htmlAttributes = new { @class = "form-control" } })
|
||||||
|
@Html.ValidationMessageFor(model => model.patientEmail, "", new { @class = "text-danger" })
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post">
|
<div class="form-group">
|
||||||
@ViewBag.appointment
|
@Html.LabelFor(model => model.imageFile, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||||
</form>
|
<div class="col-md-10">
|
||||||
|
<input type="file" name="imageFile" id="imageFile" accept="image/png, image/jpeg" />
|
||||||
|
@Html.ValidationMessageFor(model => model.imageFile, "", new { @class = "text-danger" })
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-offset-2 col-md-10">
|
||||||
|
<input type="submit" value="Create" class="btn btn-default" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@Scripts.Render("~/bundles/jqueryval")
|
@Scripts.Render("~/bundles/jqueryval")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user