✨ Event Calendar
This commit is contained in:
parent
b370c69670
commit
4fd8a588fa
@ -257,7 +257,7 @@ public class AccountController(
|
|||||||
.OrderByDescending(s => s.CreatedAt)
|
.OrderByDescending(s => s.CreatedAt)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
if (status is null) return NotFound();
|
if (status is null) return NotFound();
|
||||||
|
|
||||||
await events.ClearStatus(currentUser, status);
|
await events.ClearStatus(currentUser, status);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
@ -268,31 +268,31 @@ public class AccountController(
|
|||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
|
||||||
var userId = currentUser.Id;
|
var userId = currentUser.Id;
|
||||||
|
|
||||||
var today = SystemClock.Instance.GetCurrentInstant().InUtc().Date;
|
var today = SystemClock.Instance.GetCurrentInstant().InUtc().Date;
|
||||||
var localTime = new TimeOnly(0, 0);
|
var localTime = new TimeOnly(0, 0);
|
||||||
var startOfDay = today.ToDateOnly().ToDateTime(localTime).ToUniversalTime().ToInstant();
|
var startOfDay = today.ToDateOnly().ToDateTime(localTime).ToUniversalTime().ToInstant();
|
||||||
var endOfDay = today.PlusDays(1).ToDateOnly().ToDateTime(localTime).ToUniversalTime().ToInstant();
|
var endOfDay = today.PlusDays(1).ToDateOnly().ToDateTime(localTime).ToUniversalTime().ToInstant();
|
||||||
|
|
||||||
var result = await db.AccountCheckInResults
|
var result = await db.AccountCheckInResults
|
||||||
.Where(x => x.AccountId == userId)
|
.Where(x => x.AccountId == userId)
|
||||||
.Where(x => x.CreatedAt >= startOfDay && x.CreatedAt < endOfDay)
|
.Where(x => x.CreatedAt >= startOfDay && x.CreatedAt < endOfDay)
|
||||||
.OrderByDescending(x => x.CreatedAt)
|
.OrderByDescending(x => x.CreatedAt)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
return result is null ? NotFound() : Ok(result);
|
return result is null ? NotFound() : Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("me/check-in")]
|
[HttpPost("me/check-in")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<ActionResult<CheckInResult>> DoCheckIn([FromBody] string? captchaToken)
|
public async Task<ActionResult<CheckInResult>> DoCheckIn([FromBody] string? captchaToken)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
|
||||||
|
|
||||||
var isAvailable = await events.CheckInDailyIsAvailable(currentUser);
|
var isAvailable = await events.CheckInDailyIsAvailable(currentUser);
|
||||||
if (!isAvailable)
|
if (!isAvailable)
|
||||||
return BadRequest("Check-in is not available for today.");
|
return BadRequest("Check-in is not available for today.");
|
||||||
|
|
||||||
var needsCaptcha = events.CheckInDailyDoAskCaptcha(currentUser);
|
var needsCaptcha = events.CheckInDailyDoAskCaptcha(currentUser);
|
||||||
return needsCaptcha switch
|
return needsCaptcha switch
|
||||||
{
|
{
|
||||||
@ -303,6 +303,23 @@ public class AccountController(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("me/calendar")]
|
||||||
|
[Authorize]
|
||||||
|
public async Task<ActionResult<List<DailyEventResponse>>> GetEventCalendar([FromQuery] int? month, [FromQuery] int? year)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
|
||||||
|
|
||||||
|
var currentDate = SystemClock.Instance.GetCurrentInstant().InUtc().Date;
|
||||||
|
month ??= currentDate.Month;
|
||||||
|
year ??= currentDate.Year;
|
||||||
|
|
||||||
|
if (month is < 1 or > 12) return BadRequest("Invalid month.");
|
||||||
|
if (year < 1) return BadRequest("Invalid year.");
|
||||||
|
|
||||||
|
var calendar = await events.GetEventCalendar(currentUser, month.Value, year.Value);
|
||||||
|
return Ok(calendar);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("search")]
|
[HttpGet("search")]
|
||||||
public async Task<List<Account>> Search([FromQuery] string query, [FromQuery] int take = 20)
|
public async Task<List<Account>> Search([FromQuery] string query, [FromQuery] int take = 20)
|
||||||
{
|
{
|
||||||
|
@ -167,4 +167,45 @@ public class AccountEventService(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<DailyEventResponse>> GetEventCalendar(Account user, int month, int year = 0)
|
||||||
|
{
|
||||||
|
if (year == 0)
|
||||||
|
year = SystemClock.Instance.GetCurrentInstant().InUtc().Date.Year;
|
||||||
|
|
||||||
|
// Create start and end dates for the specified month
|
||||||
|
var startOfMonth = new LocalDate(year, month, 1).AtStartOfDayInZone(DateTimeZone.Utc).ToInstant();
|
||||||
|
var endOfMonth = startOfMonth.Plus(Duration.FromDays(DateTime.DaysInMonth(year, month)));
|
||||||
|
|
||||||
|
var statuses = await db.AccountStatuses
|
||||||
|
.Where(x => x.AccountId == user.Id && x.CreatedAt >= startOfMonth && x.CreatedAt < endOfMonth)
|
||||||
|
.OrderBy(x => x.CreatedAt)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var checkIn = await db.AccountCheckInResults
|
||||||
|
.Where(x => x.AccountId == user.Id && x.CreatedAt >= startOfMonth && x.CreatedAt < endOfMonth)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var dates = Enumerable.Range(1, DateTime.DaysInMonth(year, month))
|
||||||
|
.Select(day => new LocalDate(year, month, day).AtStartOfDayInZone(DateTimeZone.Utc).ToInstant())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var statusesByDate = statuses
|
||||||
|
.GroupBy(s => s.CreatedAt.InUtc().Date)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
var checkInByDate = checkIn
|
||||||
|
.ToDictionary(c => c.CreatedAt.InUtc().Date);
|
||||||
|
|
||||||
|
return dates.Select(date =>
|
||||||
|
{
|
||||||
|
var utcDate = date.InUtc().Date;
|
||||||
|
return new DailyEventResponse
|
||||||
|
{
|
||||||
|
Date = date,
|
||||||
|
CheckInResult = checkInByDate.GetValueOrDefault(utcDate),
|
||||||
|
Statuses = statusesByDate.GetValueOrDefault(utcDate, new List<Status>())
|
||||||
|
};
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
@ -49,4 +49,14 @@ public class FortuneTip
|
|||||||
public bool IsPositive { get; set; }
|
public bool IsPositive { get; set; }
|
||||||
public string Title { get; set; } = null!;
|
public string Title { get; set; } = null!;
|
||||||
public string Content { get; set; } = null!;
|
public string Content { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method should not be mapped. Used to generate the daily event calendar.
|
||||||
|
/// </summary>
|
||||||
|
public class DailyEventResponse
|
||||||
|
{
|
||||||
|
public Instant Date { get; set; }
|
||||||
|
public CheckInResult? CheckInResult { get; set; }
|
||||||
|
public ICollection<Status> Statuses { get; set; } = new List<Status>();
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user