Compare commits

1 Commits

Author SHA1 Message Date
saidamirkattan e8b105f155 Add Taske UI source files 2026-08-07 02:42:24 +03:00
12 changed files with 410 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Tasks.Module.Components.Pages.TasksPage).Assembly }">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
+143
View File
@@ -0,0 +1,143 @@
@inherits LayoutComponentBase
@using Tasks.Module.Services
@using Tasks.Module.Models
@using Tasks.Module.Components.Dialogs
@inject IViewService ViewService
@inject IDialogService DialogService
<MudThemeProvider />
<MudPopoverProvider />
<MudDialogProvider />
<MudSnackbarProvider />
<MudLayout>
<MudAppBar Elevation="1">
<MudText Typo="Typo.h5">Taske</MudText>
<MudSpacer />
</MudAppBar>
<MudDrawer Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Width="300px" Anchor="Anchor.Start" Variant="DrawerVariant.Persistent">
<MudStack Orientation="Orientation.Vertical" Spacing="0" Style="height: 100%;">
@* My Tasks Section *@
<div class="pa-2">
<MudLink Href="/tasks" Underline="Underline.None" Class="d-flex align-center pa-2 rounded">
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Primary" Class="mr-2" />
<MudText Typo="Typo.body1" Color="Color.Default">My Tasks</MudText>
</MudLink>
</div>
<div style="height: 1px; background-color: var(--mud-palette-lines-default); margin: 0 8px;"></div>
@* Categories Section *@
<div class="pa-2">
<div class="d-flex align-center justify-space-between px-2 py-1">
<MudLink Href="/tasks/categories" Underline="Underline.None" Class="flex-grow-1">
<MudText Typo="Typo.caption" Color="Color.Default">CATEGORIES</MudText>
</MudLink>
</div>
</div>
<div style="height: 1px; background-color: var(--mud-palette-lines-default); margin: 0 8px;"></div>
@* Tags Section *@
<div class="pa-2">
<div class="d-flex align-center justify-space-between px-2 py-1">
<MudLink Href="/tasks/tags" Underline="Underline.None" Class="flex-grow-1">
<MudText Typo="Typo.caption" Color="Color.Default">TAGS</MudText>
</MudLink>
</div>
</div>
<div style="height: 1px; background-color: var(--mud-palette-lines-default); margin: 0 8px;"></div>
@* Views Section *@
<div class="pa-2">
<div class="d-flex align-center justify-space-between px-2 py-1">
<MudText Typo="Typo.caption" Color="Color.Default">VIEWS</MudText>
<MudIconButton Icon="@Icons.Material.Filled.Add" Size="Size.Small" Color="Color.Inherit" OnClick="CreateView" ToolTip="Create View" />
</div>
@if (_loadingViews)
{
<MudProgressLinear Indeterminate="true" Class="my-2" />
}
else
{
@foreach (var view in _views)
{
<MudLink Href="@($"/tasks/view/{view.Id}")" Underline="Underline.None" Class="d-flex align-center pa-2 rounded">
<MudIcon Icon="@Icons.Material.Filled.ViewKanban" Color="Color.Default" Class="mr-2" Size="Size.Small" />
<MudText Typo="Typo.body2" Color="Color.Default">@view.Name</MudText>
</MudLink>
}
}
</div>
<div style="height: 1px; background-color: var(--mud-palette-lines-default); margin: 0 8px;"></div>
@* Files Section *@
<div style="flex: 1; overflow-y: auto; min-height: 0;">
<FolderSidebar />
</div>
</MudStack>
</MudDrawer>
<MudMainContent>
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="my-4">
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
<style>
.mud-link:hover {
background-color: var(--mud-palette-action-default-hover);
}
</style>
@code {
private bool _drawerOpen = true;
private List<TaskViewDto> _views = new();
private bool _loadingViews = true;
protected override async Task OnInitializedAsync()
{
await LoadViews();
}
private async Task LoadViews()
{
_loadingViews = true;
try
{
_views = await ViewService.GetAllViewsAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Error loading views: {ex.Message}");
}
finally
{
_loadingViews = false;
}
}
private async Task CreateView()
{
var parameters = new DialogParameters<CreateViewDialog>();
var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small, FullWidth = true };
var dialog = await DialogService.ShowAsync<CreateViewDialog>("Create View", parameters, options);
var result = await dialog.Result;
if (result is { Canceled: false } && result.Data is CreateTaskViewDto createDto)
{
try
{
var newView = await ViewService.CreateViewAsync(createDto);
_views.Add(newView);
StateHasChanged();
}
catch (Exception ex)
{
Console.WriteLine($"Error creating view: {ex.Message}");
}
}
}
}
+9
View File
@@ -0,0 +1,9 @@
@page "/"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo("/tasks");
}
}
+8
View File
@@ -0,0 +1,8 @@
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo("/tasks", forceLoad: true);
}
}
+37
View File
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MudBlazor;
using MudBlazor.Services;
using Tasks.Module.Services;
using UI;
using UI.Components;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
// Configure HTTP client for Tasks API
var tasksApiUrl = builder.Configuration["ApiSettings:TasksUrl"] ?? "http://localhost:5000";
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(tasksApiUrl) });
// Add MudBlazor services
builder.Services.AddMudServices(config =>
{
config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight;
config.SnackbarConfiguration.PreventDuplicates = false;
config.SnackbarConfiguration.ShowCloseIcon = true;
config.SnackbarConfiguration.VisibleStateDuration = 3000;
config.SnackbarConfiguration.HideTransitionDuration = 100;
config.SnackbarConfiguration.ShowTransitionDuration = 100;
config.SnackbarConfiguration.SnackbarVariant = Variant.Filled;
});
// Register services
builder.Services.AddScoped<ITodoService, TodoService>();
builder.Services.AddScoped<IFolderService, FolderService>();
builder.Services.AddScoped<IViewService, Tasks.Module.Services.ViewService>();
builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<ITagService, TagService>();
await builder.Build().RunAsync();
+14
View File
@@ -0,0 +1,14 @@
{
"profiles": {
"UI": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy",
"applicationUrl": "http://localhost:5173",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<RunAOTCompilation>false</RunAOTCompilation>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MudBlazor" Version="8.9.0" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libs\Modules\Tasks.Module\Tasks.Module.csproj" />
<ProjectReference Include="..\..\..\Libs\Layouts\LayoutLib.Layout\LayoutLib.Layout.csproj" />
</ItemGroup>
</Project>
+17
View File
@@ -0,0 +1,17 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using MudBlazor
@using UI
@using UI.Components
@using UI.Components.Layout
@using UI.Components.Pages
@using Tasks.Module
@using Tasks.Module.Components
@using Tasks.Module.Components.Sidebar
@using Tasks.Module.Services
@using Tasks.Module.Models
+11
View File
@@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./**/*.{razor,html,cs}",
"./_content/MudBlazor/**/*.{razor,html,cs}"
],
theme: {
extend: {},
},
plugins: [],
}
+5
View File
@@ -0,0 +1,5 @@
{
"ApiSettings": {
"TasksUrl": "http://localhost:5000"
}
}
+105
View File
@@ -0,0 +1,105 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
html, body {
font-family: 'Roboto', sans-serif;
}
/* Custom styles */
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.items-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.gap-2 {
gap: 0.5rem;
}
.gap-3 {
gap: 0.75rem;
}
.mb-3 {
margin-bottom: 0.75rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.mt-2 {
margin-top: 0.5rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.ml-2 {
margin-left: 0.5rem;
}
.ml-4 {
margin-left: 1rem;
}
.ml-8 {
margin-left: 2rem;
}
.pl-4 {
padding-left: 1rem;
}
.pa-4 {
padding: 1rem;
}
.pa-8 {
padding: 2rem;
}
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.text-center {
text-align: center;
}
.text-gray-500 {
color: #6b7280;
}
.text-red-500 {
color: #ef4444;
}
.line-through {
text-decoration: line-through;
}
.opacity-70 {
opacity: 0.7;
}
.border-l-2 {
border-left-width: 2px;
}
.border-gray-300 {
border-color: #d1d5db;
}
+21
View File
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Taske</title>
<base href="/" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
</body>
</html>