Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public partial class MainPageModel : ObservableObject, IProjectTaskPageModel
[ObservableProperty]
private string _today = DateTime.Now.ToString("dddd, MMM d");

[ObservableProperty]
private Project? selectedProject;

public bool HasCompletedTasks
=> Tasks?.Any(t => t.IsCompleted) ?? false;

Expand Down Expand Up @@ -149,8 +152,8 @@ private Task AddTask()
=> Shell.Current.GoToAsync($"task");

[RelayCommand]
private Task NavigateToProject(Project project)
=> Shell.Current.GoToAsync($"project?id={project.ID}");
private Task? NavigateToProject(Project project)
=> project is null ? null : Shell.Current.GoToAsync($"project?id={project.ID}");
Comment on lines +155 to +156
Copy link
Preview

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method returns Task? which creates an inconsistent API design. Consider throwing ArgumentNullException for null projects or restructuring to always return a completed Task to maintain a consistent return type.

Copilot uses AI. Check for mistakes.

Comment on lines +155 to +156
Copy link
Preview

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method should return a consistent Task type rather than nullable Task. Consider returning Task.CompletedTask for null projects instead of null to maintain a consistent async pattern.

Suggested change
private Task? NavigateToProject(Project project)
=> project is null ? null : Shell.Current.GoToAsync($"project?id={project.ID}");
private Task NavigateToProject(Project project)
=> project is null ? Task.CompletedTask : Shell.Current.GoToAsync($"project?id={project.ID}");

Copilot uses AI. Check for mistakes.


[RelayCommand]
private Task NavigateToTask(ProjectTask task)
Expand Down
55 changes: 33 additions & 22 deletions src/Templates/src/templates/maui-mobile/Pages/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,37 @@
RefreshCommand="{Binding RefreshCommand}">
<pullToRefresh:SfPullToRefresh.PullableContent>
<ScrollView>
<VerticalStackLayout Spacing="{StaticResource LayoutSpacing}" Padding="{StaticResource LayoutPadding}">
<Label Text="Task Categories" Style="{StaticResource Title2}" SemanticProperties.HeadingLevel="Level1"/>
<controls:CategoryChart />
<Label Text="Projects" Style="{StaticResource Title2}" SemanticProperties.HeadingLevel="Level1"/>
<ScrollView Orientation="Horizontal" Margin="-30,0">
<HorizontalStackLayout
Spacing="15" Padding="30,0"
BindableLayout.ItemsSource="{Binding Projects}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="models:Project">
<controls:ProjectCardView WidthRequest="200">
<controls:ProjectCardView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding NavigateToProjectCommand, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:MainPageModel}" CommandParameter="{Binding .}"/>
</controls:ProjectCardView.GestureRecognizers>
</controls:ProjectCardView>
</DataTemplate>
</BindableLayout.ItemTemplate>
</HorizontalStackLayout>
</ScrollView>
<Grid MinimumHeightRequest="44">
<Grid RowSpacing="{StaticResource LayoutSpacing}" Padding="{StaticResource LayoutPadding}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<Label Grid.Row="0" Text="Task Categories" Style="{StaticResource Title2}" SemanticProperties.HeadingLevel="Level1"/>
<controls:CategoryChart Grid.Row="1" />
<Label Grid.Row="2" Text="Projects" Style="{StaticResource Title2}" SemanticProperties.HeadingLevel="Level1"/>
<CollectionView Grid.Row="3" ItemsSource="{Binding Projects}"
Margin="-7.5,0"
MinimumHeightRequest="250"
x:Name="ProjectsCollectionView"
SelectionMode="Single"
SelectedItem="{Binding SelectedProject}"
SelectionChangedCommand="{Binding NavigateToProjectCommand, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:MainPageModel}"
SelectionChangedCommandParameter="{Binding SelectedProject}">
Comment on lines +60 to +61
Copy link
Preview

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SelectionChangedCommandParameter binding to SelectedProject is redundant since the SelectedItem is already bound to SelectedProject. The command can access the selected project directly through the SelectedProject property, eliminating the need for the command parameter.

Suggested change
SelectionChangedCommand="{Binding NavigateToProjectCommand, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:MainPageModel}"
SelectionChangedCommandParameter="{Binding SelectedProject}">
SelectionChangedCommand="{Binding NavigateToProjectCommand, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:MainPageModel}">

Copilot uses AI. Check for mistakes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, can simplify it because the command can access the selected project directly through the SelectedProject property. I'm ok with both options.

<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" ItemSpacing="7.5"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:Project">
<controls:ProjectCardView WidthRequest="200" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Grid Grid.Row="4" MinimumHeightRequest="44">
<Label Text="Tasks" Style="{StaticResource Title2}" VerticalOptions="Center" SemanticProperties.HeadingLevel="Level1"/>
<ImageButton
Source="{StaticResource IconClean}"
Expand All @@ -70,15 +81,15 @@
Command="{Binding CleanTasksCommand}"
SemanticProperties.Description="Clean tasks" />
</Grid>
<VerticalStackLayout Spacing="15"
<VerticalStackLayout Grid.Row="5" Spacing="15"
BindableLayout.ItemsSource="{Binding Tasks}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<controls:TaskView TaskCompletedCommand="{Binding TaskCompletedCommand, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:MainPageModel}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
</VerticalStackLayout>
</Grid>
</ScrollView>
</pullToRefresh:SfPullToRefresh.PullableContent>
</pullToRefresh:SfPullToRefresh>
Expand Down
Loading