iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
自我挑戰組

用 30 天和 ASP.NET Core 打造一個活動報名管理系統系列 第 27

活動報名管理系統:Day27 完成取消活動報名、刪除報名資訊即無法報名的功能

  • 分享至 

  • xImage
  •  

前言

昨天將活動報名以及儲存報名者資訊的功能做好了,而今天要再加上取消報名的功能,以及在頁面顯示當前活動報名人數。

Repository

EventsRepository

Repository 先前已經完成了刪除報名使用者資料功能了,但還要再新增一個撈取該活動所有 EventsEnroll 的 Function,讓後續可以在 Services 新增一個比對當前使用者的報名資料是否存在於 EventsEnroll 內。

建立以「活動ID」撈取 EventsEnroll 的 Function:

public async Task<IEnumerable<EventsEnroll>> GetEventsEnrollByEventIdAsync(int eventId)
{
            var eventsEnrolls = await _appDbContext.EventsEnroll.Where(
                ee => ee.Events.Id == eventId
                ).ToListAsync();

            return eventsEnrolls;
}

Service

EventsApplyServices

建立與 GetEventsEnrollByEventIdAsync() 取得的活動比對當前使用者是否被存在於資料內的 Function:

public async Task<bool> IsUserAlreadyEnroll(int id, string userId)
        {
            try
            {
                if(id > 0 && !string.IsNullOrEmpty(userId))
                {
                    var eventsEnrolls = await _eventsRepository.GetEventsEnrollsByEventIdAsync(id);

                    var userInEnroll = eventsEnrolls.Where(
                        ee => ee.ApplicationUserId == userId
                        ).FirstOrDefault();

                    if(userInEnroll == null)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    throw new Exception("判斷使用者是否在活動報名資料內錯誤。 ID not valid");
                }
            }
            catch (Exception)
            {
                throw new Exception("判斷使用者是否在活動報名資料內錯誤。");
            }
        }

Controller

EventsController

EventsEnroll

修正 EventsEnroll 在判斷是否符合可報名條件(在報名時間內 & 是否已額滿)的邏輯,加入是否已報名:

if (isInEventsSalesTime == true && isApplicationLimitedQtyFull == false
        && !await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
{
    await _eventsRepository.SaveUserInfoToEventsEnrollAsync(EventsEnroll);
    TempData["Message"] = "報名成功";
}
else
{
    TempData["Message"] = "報名失敗";
}

Details

public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var @event = await _eventsRepository.GetEventByIdAsync(id);
            if (@event == null)
            {
                return NotFound();
            }

            EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
            var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
            if (!await EventsApplyServices.IsApplicationLimitedQtyFull(@event) && EventsApplyServices.IsInEventsSalesTime(@event))
            {
                if (await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
                {
                    ViewData["EnrollBtn"] = 2;
                }
                else
                {
                    ViewData["EnrollBtn"] = 1;
                }
            }
            else
            {
                ViewData["EnrollBtn"] = 3;
            }

            return View(@event);
        }

CancelEventsEnroll

新增 CancelEventsEnroll 取消報名 Action:

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> CancelEventsEnroll(int? id)
        {
            Events Event = new Events();
            try
            {
                if (id != null)
                {
                    Event = await _eventsRepository.GetEventByIdAsync(id);
                    EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
                    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

                    EventsEnroll EventsEnroll = new EventsEnroll()
                    {
                        Events = Event,
                        ApplicationUserId = userId
                    };

                    if (Event != null && await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
                    {
                        await _eventsRepository.DeleteUserInfoFromEventsEnrollAsync(EventsEnroll);
                        TempData["Message"] = "取消報名成功";
                    }
                    else
                    {
                        TempData["Message"] = "取消報名失敗";
                    }
                }
                else
                {
                    return BadRequest();
                }
            }
            catch (Exception)
            {
                throw new Exception("取消報名失敗");
            }

            return RedirectToAction("Details", Event);
        }

View

Details

將報名按鈕加入邏輯,可直接顯示是否允許報名,並將 Form Tag 移到判斷式內,使判斷式可動態切換要使用的 Action:

@{
        switch ((int)ViewData["EnrollBtn"])
        {
            case 1:
                <form asp-action="EventsEnroll" method="post" style="display:inline;">
                    <input type="hidden" asp-for="Id" />
                    <input type="submit" value="報名" class="btn btn-primary" />
                </form>
                break;

            case 2:
                <form asp-action="CancelEventsEnroll" method="post" style="display:inline;">
                    <input type="submit" value="取消報名" class="btn btn-danger" />
                    <input type="hidden" asp-for="Id" />
                </form>
                break;

            default:
                <input type="button" value="無法報名" class="btn btn-primary" disabled/>
                break;
        }
    }

實際結果

不在票券販賣時間內時,顯示無法報名:

在票券販賣時間內時且尚未報名,顯示報名:

在票券販賣時間內時且已經報名,顯示取消報名:

本日結語

今天將取消報名與不在時間內無法報名的邏輯做好了,明天預計會使用一下 Partial View,將提示訊息用 Partial View 的方式來顯示。

也預計將一些按鈕是否顯示的部分做好,例如說只有活動舉辦者才可以顯示編輯按鈕等等的。

那麼我們明天見!


上一篇
ASP.NET Core - 活動報名管理系統:Day26 Repository、Controller 與 Services 加入活動報名與儲存報名資訊的功能
下一篇
ASP.NET Core - 活動報名管理系統:Day28 用 Partial View 顯示 Bootstrap Alert 以及改善活動功能的執行權限
系列文
用 30 天和 ASP.NET Core 打造一個活動報名管理系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言