Compare commits
	
		
			6 Commits
		
	
	
		
			c3c09f8966
			...
			30c3fbcadc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 30c3fbcadc | |||
| ce5f7a5d8c | |||
| fbcebd47d9 | |||
| 9d483caa68 | |||
| 80f8026d09 | |||
| 12530059ee | 
| 
						 | 
				
			
			@ -28,6 +28,12 @@ namespace FIT5032_Assignment {
 | 
			
		|||
        url: "Appointments",
 | 
			
		||||
        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,9 +16,24 @@ using Org.BouncyCastle.Security;
 | 
			
		|||
using System.IO;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using RestSharp.Authenticators;
 | 
			
		||||
using RestSharp;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
namespace FIT5032_Assignment.Controllers {
 | 
			
		||||
  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();
 | 
			
		||||
 | 
			
		||||
    // Login check
 | 
			
		||||
| 
						 | 
				
			
			@ -93,13 +108,142 @@ namespace FIT5032_Assignment.Controllers {
 | 
			
		|||
 | 
			
		||||
    // GET: Appointments
 | 
			
		||||
    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"];
 | 
			
		||||
      return View();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // GET: Appointments/Details/5
 | 
			
		||||
    public ActionResult Details(int id) {
 | 
			
		||||
      return View();
 | 
			
		||||
    // GET: Appointments/Cancel/uuid
 | 
			
		||||
    public ActionResult Cancel(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");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 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
 | 
			
		||||
| 
						 | 
				
			
			@ -202,40 +346,227 @@ namespace FIT5032_Assignment.Controllers {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // GET: Appointments/Edit/5
 | 
			
		||||
    public ActionResult Edit(int id) {
 | 
			
		||||
    // GET: Appointments/UploadImage/uuid
 | 
			
		||||
    public ActionResult UploadImage(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;
 | 
			
		||||
      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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // POST: Appointments/Edit/5
 | 
			
		||||
    [HttpPost]
 | 
			
		||||
    public ActionResult Edit(int id, FormCollection collection) {
 | 
			
		||||
    public async Task<ActionResult> UploadImage(HttpPostedFileBase image, string appointmentUuid) {
 | 
			
		||||
      try {
 | 
			
		||||
        // TODO: Add update logic here
 | 
			
		||||
        // 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");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return RedirectToAction("Index");
 | 
			
		||||
      }
 | 
			
		||||
      catch {
 | 
			
		||||
        return View();
 | 
			
		||||
        // Check the appointment exist & status == 1 & responsibleBy == doctor
 | 
			
		||||
        var appointment = db.Appointments.Find(appointmentUuid);
 | 
			
		||||
        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");
 | 
			
		||||
        }
 | 
			
		||||
        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");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // GET: Appointments/Delete/5
 | 
			
		||||
    public ActionResult Delete(int id) {
 | 
			
		||||
    public ActionResult Detail(string id) {
 | 
			
		||||
      // Verify 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;
 | 
			
		||||
 | 
			
		||||
      // 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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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,6 +52,7 @@ namespace FIT5032_Assignment.Controllers {
 | 
			
		|||
    public DbSet<Patients> Patients { get; set; }
 | 
			
		||||
    public DbSet<Doctors> Doctors { get; set; }
 | 
			
		||||
    public DbSet<Appointments> Appointments { get; set; }
 | 
			
		||||
    public DbSet<Images> Images { get; set; }
 | 
			
		||||
  }
 | 
			
		||||
  public class HomeController : Controller {
 | 
			
		||||
    public static string GetMd5Hash(string input) {
 | 
			
		||||
| 
						 | 
				
			
			@ -168,6 +169,10 @@ namespace FIT5032_Assignment.Controllers {
 | 
			
		|||
              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();
 | 
			
		||||
| 
						 | 
				
			
			@ -407,6 +412,8 @@ namespace FIT5032_Assignment.Controllers {
 | 
			
		|||
        return new HttpStatusCodeResult(HttpStatusCode.BadGateway);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								FIT5032-Assignment/Controllers/System.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								FIT5032-Assignment/Controllers/System.cs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
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,6 +186,7 @@
 | 
			
		|||
    <Compile Include="App_Start\RouteConfig.cs" />
 | 
			
		||||
    <Compile Include="Controllers\AppointmentsController.cs" />
 | 
			
		||||
    <Compile Include="Controllers\HomeController.cs" />
 | 
			
		||||
    <Compile Include="Controllers\System.cs" />
 | 
			
		||||
    <Compile Include="Global.asax.cs">
 | 
			
		||||
      <DependentUpon>Global.asax</DependentUpon>
 | 
			
		||||
    </Compile>
 | 
			
		||||
| 
						 | 
				
			
			@ -322,10 +323,13 @@
 | 
			
		|||
    <Content Include="Views\Home\ImageUpload.cshtml" />
 | 
			
		||||
    <Content Include="Views\Appointments\Index.cshtml" />
 | 
			
		||||
    <Content Include="Views\Appointments\Create.cshtml" />
 | 
			
		||||
    <Content Include="Views\Appointments\CreateByDoctor.cshtml" />
 | 
			
		||||
    <Content Include="Views\Appointments\UploadImage.cshtml" />
 | 
			
		||||
    <Content Include="Views\Appointments\Detail.cshtml" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="App_Data\upload_images\" />
 | 
			
		||||
    <Folder Include="Views\Default\" />
 | 
			
		||||
    <Folder Include="Views\System\" />
 | 
			
		||||
    <Folder Include="Views\Test\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
    <IISExpressUseClassicPipelineMode />
 | 
			
		||||
    <UseGlobalApplicationHostFile />
 | 
			
		||||
    <LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
 | 
			
		||||
    <Controller_SelectedScaffolderID>MvcControllerWithActionsScaffolder</Controller_SelectedScaffolderID>
 | 
			
		||||
    <Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
 | 
			
		||||
    <Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
 | 
			
		||||
    <WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
 | 
			
		||||
    <WebStackScaffolding_LayoutPageFile>~/Views/Shared/_Layout.cshtml</WebStackScaffolding_LayoutPageFile>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										118
									
								
								FIT5032-Assignment/Views/Appointments/Detail.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								FIT5032-Assignment/Views/Appointments/Detail.cshtml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
 | 
			
		||||
@{
 | 
			
		||||
    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";
 | 
			
		||||
    Layout = "~/Views/Shared/_Layout.cshtml";
 | 
			
		||||
  ViewBag.Title = "Appointments";
 | 
			
		||||
  Layout = "~/Views/Shared/_Layout.cshtml";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@if (ViewBag.tip != null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -10,8 +10,141 @@
 | 
			
		|||
  </div>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<h2>Appointments</h2>
 | 
			
		||||
<div class="titlebar">
 | 
			
		||||
  <h2>My appointments</h2>
 | 
			
		||||
  @if (ViewBag.role == 1) {<a href="./Create" class="btn btn-primary">Make a new appointment</a>}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
  <li><a href="./Create">Make a new appointment</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
@if (ViewBag.role == 1) {
 | 
			
		||||
  <table class="table table-hover">
 | 
			
		||||
    <tr>
 | 
			
		||||
      <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>
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								FIT5032-Assignment/Views/Appointments/UploadImage.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								FIT5032-Assignment/Views/Appointments/UploadImage.cshtml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
@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,38 +4,11 @@
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@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>
 | 
			
		||||
<h2>Upload image</h2>
 | 
			
		||||
 | 
			
		||||
        <div class="form-group">
 | 
			
		||||
            @Html.LabelFor(model => model.imageFile, htmlAttributes: new { @class = "control-label col-md-2" })
 | 
			
		||||
            <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>
 | 
			
		||||
}
 | 
			
		||||
<form method="post">
 | 
			
		||||
  @ViewBag.appointment
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
@section Scripts {
 | 
			
		||||
    @Scripts.Render("~/bundles/jqueryval")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user