feat: agregar SyncService y mejorar gestión de asistencia con nuevas funcionalidades

This commit is contained in:
Nurfog committed 2026-08-20 10:45:53 -04:00
1 parent fb275508ee
commit d953afd3b4
15 files changed
+339 -359

No files matched your search

+72 -93
View File
@@ -4,130 +4,109 @@
x:Class="Asistencia.Views.AsistenciaView"
x:DataType="vm:AsistenciaViewModel">
<Design.DataContext>
<vm:AsistenciaViewModel />
</Design.DataContext>
<ScrollViewer>
<StackPanel Spacing="0" Margin="32,24">
<StackPanel Spacing="0" Margin="32,24" MaxWidth="500">
<Button Content="Volver" Classes="secondary"
HorizontalAlignment="Left"
Command="{Binding VolverCommand}"
Margin="0,0,0,16" />
<TextBlock Text="{Binding NombreCurso}" Classes="page-header" />
<TextBlock Text="Tomar Asistencia" Classes="page-header" />
<Border Classes="card" Margin="0,0,0,20">
<StackPanel Spacing="8">
<TextBlock Text="{Binding InfoCurso}"
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding MensajeEstado}"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryNavy}" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,8,0,0">
<Button Content="Iniciar Sesion"
Classes="success"
<Border Classes="card" Margin="0,0,0,16">
<StackPanel Spacing="12">
<TextBlock Text="ID Curso Abierto" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<TextBox PlaceholderText="Ej: 16451"
Text="{Binding InputCursoAbierto}"
FontSize="14" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Iniciar Sesion" Classes="success"
Command="{Binding IniciarSesionCommand}"
IsVisible="{Binding !EnSesion}" />
<Button Content="Finalizar Sesion"
Classes="danger"
<Button Content="Finalizar Sesion" Classes="danger"
Command="{Binding FinalizarSesionCommand}"
IsVisible="{Binding EnSesion}" />
</StackPanel>
</StackPanel>
</Border>
<Grid ColumnDefinitions="*,Auto" Margin="0,0,0,16">
<TextBlock Grid.Column="0"
Classes="section-title"
Text="Alumnos"
VerticalAlignment="Center" />
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="16">
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource SuccessColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Presentes}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource WarningColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Tardanzas}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="4">
<Border Background="{DynamicResource DangerColor}"
CornerRadius="4" Width="12" Height="12" />
<TextBlock Text="{Binding Ausentes}" FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<Border Classes="card" Margin="0,0,0,16"
IsVisible="{Binding EnSesion}">
<StackPanel Spacing="12">
<TextBlock Text="RUT Alumno" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0"
PlaceholderText="Ej: 11111111-1"
Text="{Binding InputRutAlumno}"
FontSize="14"
KeyDown="OnRutAlumnoKeyDown" />
<Button Grid.Column="1"
Content="+"
Classes="primary"
Command="{Binding AgregarAlumnoCommand}"
Margin="8,0,0,0"
Width="40" Height="40"
FontSize="18" FontWeight="Bold" />
</Grid>
</StackPanel>
</Grid>
</Border>
<Border Classes="card" Padding="0">
<Grid RowDefinitions="Auto,*">
<TextBlock Text="{Binding MensajeEstado}"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryNavy}"
Margin="0,0,0,12"
IsVisible="{Binding !HasError}" />
<Border Grid.Row="0" Background="{DynamicResource BackgroundSecondary}"
<TextBlock Text="{Binding MensajeError}"
FontSize="13"
Foreground="{DynamicResource DangerColor}"
Margin="0,0,0,12"
IsVisible="{Binding HasError}" />
<Border Classes="card" Padding="0"
IsVisible="{Binding EnSesion}">
<StackPanel>
<Border Background="{DynamicResource BackgroundSecondary}"
CornerRadius="12,12,0,0" Padding="16,12">
<Grid ColumnDefinitions="*,120">
<TextBlock Grid.Column="0" Text="Alumno"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Grid.Column="1" Text="Estado"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondary}"
HorizontalAlignment="Center" />
</Grid>
<TextBlock Text="Alumnos Presentes"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondary}" />
</Border>
<ListBox Grid.Row="1"
ItemsSource="{Binding Alumnos}"
<ListBox ItemsSource="{Binding AlumnosPresentes}"
Background="Transparent"
BorderThickness="0"
Padding="0">
Padding="0"
MaxHeight="300">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:AlumnoAsistenciaViewModel">
<Border Padding="16,12"
<DataTemplate x:DataType="vm:AlumnoPresenteViewModel">
<Border Padding="16,10"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,0,0,1">
<Grid ColumnDefinitions="*,120">
<TextBlock Grid.Column="0"
Text="{Binding NombreCompleto}"
FontSize="14"
VerticalAlignment="Center" />
<Button Grid.Column="1"
HorizontalAlignment="Center"
Command="{Binding $parent[ListBox].((vm:AsistenciaViewModel)DataContext).MarcarAlumnoCommand}"
CommandParameter="{Binding}"
Background="{Binding TipoAsistenciaColor}"
CornerRadius="20"
Padding="16,6"
FontSize="13"
FontWeight="SemiBold"
Foreground="White"
BorderThickness="0"
MinWidth="100">
<TextBlock Text="{Binding TipoAsistenciaTexto}"
Foreground="White" />
</Button>
<Grid ColumnDefinitions="Auto,*">
<Border Grid.Column="0"
Background="{DynamicResource SuccessColor}"
CornerRadius="12" Padding="10,4"
VerticalAlignment="Center">
<TextBlock Text="P" Foreground="White"
FontSize="12" FontWeight="Bold" />
</Border>
<StackPanel Grid.Column="1" Margin="12,0,0,0"
VerticalAlignment="Center">
<TextBlock Text="{Binding NombreCompleto}"
FontSize="14" FontWeight="SemiBold" />
<TextBlock Text="{Binding IdAlumno}"
FontSize="12"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
<Border Classes="card" Margin="0,16,0,0"
IsVisible="{Binding !Alumnos.Count}"
Background="#FFF3CD">
<TextBlock Text="No hay alumnos en este curso."
FontSize="14" Foreground="#856404" />
</StackPanel>
</Border>
</StackPanel>
+10 -1
View File
@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Input;
using Asistencia.ViewModels;
namespace Asistencia.Views;
@@ -9,4 +10,12 @@ public partial class AsistenciaView : UserControl
{
InitializeComponent();
}
private void OnRutAlumnoKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Return && DataContext is AsistenciaViewModel vm)
{
vm.AgregarAlumnoCommand.Execute(null);
}
}
}
+35 -52
View File
@@ -1,7 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Asistencia.ViewModels"
xmlns:models="using:Asistencia.Models"
x:Class="Asistencia.Views.DashboardView"
x:DataType="vm:DashboardViewModel">
@@ -10,18 +9,19 @@
</Design.DataContext>
<ScrollViewer>
<StackPanel Spacing="0" Margin="32,24">
<StackPanel Spacing="0" Margin="32,24" MaxWidth="500">
<TextBlock Text="Panel Principal" Classes="page-header" />
<Border Classes="card" Margin="0,0,0,24">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Bienvenido"
FontSize="14" Foreground="{DynamicResource TextSecondary}" />
<TextBlock Text="{Binding NombreProfesor}"
FontSize="24" FontWeight="Bold"
FontSize="22" FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}" />
<TextBlock Text="{Binding TipoAsignacion}"
FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
@@ -35,55 +35,38 @@
</Grid>
</Border>
<TextBlock Text="Mis Cursos" Classes="section-title" Margin="0,0,0,12" />
<Button Content="Tomar Asistencia"
Classes="primary"
Command="{Binding AbrirAsistenciaCommand}"
HorizontalAlignment="Stretch"
Height="50"
FontSize="16" FontWeight="SemiBold"
Margin="0,0,0,16" />
<ItemsControl ItemsSource="{Binding Cursos}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:CursoAbierto">
<Border Classes="card" Margin="0,0,0,12">
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{Binding Curso.NombreCurso}"
FontSize="18" FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}" />
<TextBlock Grid.Row="0" Grid.Column="1"
Text="{Binding Sala}"
FontSize="13"
Foreground="{DynamicResource TextSecondary}" />
<TextBlock Grid.Row="1" Grid.Column="0"
FontSize="13"
Foreground="{DynamicResource TextSecondary}"
Margin="0,4,0,0">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} | {1}">
<Binding Path="Sede" />
<Binding Path="HoraInicio" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
Content="Tomar Asistencia"
Classes="primary"
HorizontalAlignment="Left"
Margin="0,12,0,0"
Command="{Binding $parent[ItemsControl].((vm:DashboardViewModel)DataContext).AbrirAsistenciaCommand}"
CommandParameter="{Binding}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border Classes="card" Margin="0,24,0,0"
IsVisible="{Binding !Cursos.Count}"
Background="#FFF3CD">
<TextBlock Text="No tiene cursos asignados actualmente."
FontSize="14" Foreground="#856404" />
<Border Classes="card" Margin="0,0,0,16">
<StackPanel Spacing="12">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0"
FontSize="14" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}">
<TextBlock.Text>
<MultiBinding StringFormat="Pendientes: {0}">
<Binding Path="Pendientes" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Button Grid.Column="1"
Content="Sincronizar"
Classes="success"
Command="{Binding SincronizarCommand}" />
</Grid>
<TextBlock Text="{Binding MensajeSync}"
FontSize="12"
Foreground="{DynamicResource SuccessColor}"
IsVisible="{Binding HasMensajeSync}" />
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</UserControl>
+14 -7
View File
@@ -4,10 +4,6 @@
x:Class="Asistencia.Views.LoginView"
x:DataType="vm:LoginViewModel">
<Design.DataContext>
<vm:LoginViewModel />
</Design.DataContext>
<Panel Background="{DynamicResource BackgroundSecondary}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center"
CornerRadius="16" Padding="48" Width="420"
@@ -20,15 +16,26 @@
Foreground="{DynamicResource PrimaryNavy}"
HorizontalAlignment="Center" />
<TextBlock Text="Modo offline — Ingrese su RUT"
<TextBlock Text="Modo offline"
FontSize="14" Foreground="{DynamicResource TextSecondary}"
HorizontalAlignment="Center" Margin="0,0,0,24" />
<TextBlock Text="RUT" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<TextBox PlaceholderText="Ej: 12345678-9"
<TextBox PlaceholderText="Ej: 15668563-1"
Text="{Binding Rut}"
FontSize="14" Margin="0,0,0,16" />
FontSize="14" Margin="0,0,0,12" />
<TextBlock Text="Tipo de asignacion" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" Margin="0,0,0,4" />
<RadioButton Content="Titular"
IsChecked="{Binding EsTitular}"
GroupName="TipoAsignacion"
FontSize="14" />
<RadioButton Content="Reemplazo"
IsChecked="{Binding EsReemplazo}"
GroupName="TipoAsignacion"
FontSize="14" Margin="0,0,0,16" />
<Button Content="Ingresar"
Command="{Binding LoginCommand}"