Event details UI improvements.
This commit is contained in:
@@ -17,6 +17,14 @@ public class CalendarItem : ICalendarItem
|
||||
public string Description { get; set; }
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this item is a local preview that hasn't been synced to the server yet.
|
||||
/// When true, the item exists only in the local database without a RemoteEventId.
|
||||
/// Used to prevent duplicates when the server returns the newly created event.
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
public bool IsLocalPreview => string.IsNullOrEmpty(RemoteEventId);
|
||||
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
public DateTime EndDate
|
||||
@@ -187,66 +195,70 @@ public class CalendarItem : ICalendarItem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start date as a DateTimeOffset with the correct timezone.
|
||||
/// If StartTimeZone is available, uses it to calculate the offset.
|
||||
/// Otherwise, assumes UTC (StartDate is stored as UTC in database).
|
||||
/// Gets the start date converted to user's local timezone for display.
|
||||
/// StartDate is stored according to StartTimeZone.
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
public DateTimeOffset StartDateTimeOffset
|
||||
public DateTime LocalStartDate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(StartTimeZone))
|
||||
if (string.IsNullOrEmpty(StartTimeZone))
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(StartTimeZone);
|
||||
// StartDate is stored in UTC, convert to the specified timezone
|
||||
var utcDateTime = DateTime.SpecifyKind(StartDate, DateTimeKind.Utc);
|
||||
var zonedDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZoneInfo);
|
||||
var offset = timeZoneInfo.GetUtcOffset(zonedDateTime);
|
||||
return new DateTimeOffset(zonedDateTime, offset);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If timezone lookup fails, assume UTC
|
||||
}
|
||||
// No timezone info, return as-is
|
||||
return StartDate;
|
||||
}
|
||||
|
||||
// Assume UTC (StartDate is stored as UTC in database)
|
||||
return new DateTimeOffset(StartDate, TimeSpan.Zero);
|
||||
try
|
||||
{
|
||||
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(StartTimeZone);
|
||||
var localTimeZone = TimeZoneInfo.Local;
|
||||
|
||||
// Ensure DateTime is Unspecified kind before conversion
|
||||
var unspecifiedDateTime = DateTime.SpecifyKind(StartDate, DateTimeKind.Unspecified);
|
||||
|
||||
// Convert from source timezone to local timezone
|
||||
return TimeZoneInfo.ConvertTime(unspecifiedDateTime, sourceTimeZone, localTimeZone);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If timezone lookup fails, return as-is
|
||||
return StartDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the end date as a DateTimeOffset with the correct timezone.
|
||||
/// If EndTimeZone is available, uses it to calculate the offset.
|
||||
/// Otherwise, assumes UTC (EndDate is stored as UTC in database).
|
||||
/// Gets the end date converted to user's local timezone for display.
|
||||
/// EndDate is calculated from StartDate and is in StartTimeZone.
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
public DateTimeOffset EndDateTimeOffset
|
||||
public DateTime LocalEndDate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(EndTimeZone))
|
||||
if (string.IsNullOrEmpty(EndTimeZone))
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(EndTimeZone);
|
||||
// EndDate is stored in UTC, convert to the specified timezone
|
||||
var utcDateTime = DateTime.SpecifyKind(EndDate, DateTimeKind.Utc);
|
||||
var zonedDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZoneInfo);
|
||||
var offset = timeZoneInfo.GetUtcOffset(zonedDateTime);
|
||||
return new DateTimeOffset(zonedDateTime, offset);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If timezone lookup fails, assume UTC
|
||||
}
|
||||
// No timezone info, return as-is
|
||||
return EndDate;
|
||||
}
|
||||
|
||||
// Assume UTC (EndDate is stored as UTC in database)
|
||||
return new DateTimeOffset(EndDate, TimeSpan.Zero);
|
||||
try
|
||||
{
|
||||
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(EndTimeZone);
|
||||
var localTimeZone = TimeZoneInfo.Local;
|
||||
|
||||
// Ensure DateTime is Unspecified kind before conversion
|
||||
var unspecifiedDateTime = DateTime.SpecifyKind(EndDate, DateTimeKind.Unspecified);
|
||||
|
||||
// Convert from source timezone to local timezone
|
||||
return TimeZoneInfo.ConvertTime(unspecifiedDateTime, sourceTimeZone, localTimeZone);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If timezone lookup fails, return as-is
|
||||
return EndDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Wino.Core.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Defines how a calendar item should be displayed in terms of availability.
|
||||
/// </summary>
|
||||
public enum CalendarItemShowAs
|
||||
{
|
||||
Free,
|
||||
Tentative,
|
||||
Busy,
|
||||
OutOfOffice,
|
||||
WorkingElsewhere
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface ICalendarDialogService : IDialogServiceBase
|
||||
{
|
||||
}
|
||||
@@ -11,9 +11,3 @@ namespace Wino.Core.Domain.Models.Calendar;
|
||||
/// <param name="CalendarItem">Calendar item to operate on.</param>
|
||||
/// <param name="Attendees">List of attendees for the calendar event.</param>
|
||||
public record CalendarOperationPreparationRequest(CalendarSynchronizerOperation Operation, CalendarItem CalendarItem, List<CalendarEventAttendee> Attendees);
|
||||
//{
|
||||
// public CalendarOperationPreparationRequest(CalendarItem calendarItem)
|
||||
// : this(calendarItem ?? throw new ArgumentNullException(nameof(calendarItem)), null)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -83,6 +83,19 @@
|
||||
"CalendarAllDayEventSummary": "all-day events",
|
||||
"CalendarDisplayOptions_Color": "Color",
|
||||
"CalendarDisplayOptions_Expand": "Expand",
|
||||
"CalendarEventResponse_Accept": "Accept",
|
||||
"CalendarEventResponse_Decline": "Decline",
|
||||
"CalendarEventResponse_Tentative": "Tentative",
|
||||
"CalendarEventDetails_Attachments": "Attachments",
|
||||
"CalendarEventDetails_Details": "Details",
|
||||
"CalendarEventDetails_EditSeries": "Edit Series",
|
||||
"CalendarEventDetails_Editing": "Editing",
|
||||
"CalendarEventDetails_InviteSomeone": "Invite someone",
|
||||
"CalendarEventDetails_JoinOnline": "Join Online",
|
||||
"CalendarEventDetails_People": "People",
|
||||
"CalendarEventDetails_ReadOnlyEvent": "Read-only event",
|
||||
"CalendarEventDetails_Reminder": "Reminder",
|
||||
"CalendarEventDetails_ShowAs": "Show as",
|
||||
"CalendarItem_DetailsPopup_JoinOnline": "Join online",
|
||||
"CalendarItem_DetailsPopup_ViewEventButton": "View event",
|
||||
"CalendarItem_DetailsPopup_ViewSeriesButton": "View series",
|
||||
@@ -133,6 +146,8 @@
|
||||
"DialogMessage_CreateLinkedAccountTitle": "Account Link Name",
|
||||
"DialogMessage_DeleteAccountConfirmationMessage": "Delete {0}?",
|
||||
"DialogMessage_DeleteAccountConfirmationTitle": "All data associated with this account will be deleted from disk permanently.",
|
||||
"DialogMessage_DeleteRecurringSeriesMessage": "This will delete all events in the series. Do you want to continue?",
|
||||
"DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series",
|
||||
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
|
||||
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
|
||||
"DialogMessage_EmptySubjectConfirmation": "Missing Subject",
|
||||
|
||||
Reference in New Issue
Block a user