feat : not found page , authorize and version 0.2.1.10

add first version
release
Amir Hossein Khademi 2024-01-31 15:05:05 +03:30
parent 39d61e49f0
commit 9f9eaa969f
21 changed files with 2504 additions and 96 deletions

View File

@ -12,10 +12,8 @@
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
<PageTitle>پیدا نشد</PageTitle>
<NotFoundPage/>
</NotFound>

View File

@ -1,9 +1,9 @@
@inject NavigationManager NavigationManager
<MudStack class="w-full pt-8 h-screen bg-white">
@* <MudImage class="mx-15 mt-5" Src="https://vesmeh.com/wp-content/uploads/2023/02/logo-web.png.webp"></MudImage> *@
<MudTreeView T="TreeItemData" Items="@TreeItems" Hover="true" MultiSelection="false" SelectedValueChanged="SelectedChange">
<MudStack class="w-full pt-4 h-screen bg-white">
<MudImage class="mx-15 mt-5" Src="https://vesmeh.com/wp-content/uploads/2023/02/logo-web.png.webp"></MudImage>
@* <MudTreeView T="TreeItemData" Items="@TreeItems" Hover="true" MultiSelection="false" SelectedValueChanged="SelectedChange">
<ItemTemplate Context="item">
<MudTreeViewItem Value="@item" Items="@item.TreeItems" Icon="@item.Icon">
<BodyContent>
@ -13,13 +13,62 @@
</BodyContent>
</MudTreeViewItem>
</ItemTemplate>
</MudTreeView>
</MudTreeView> *@
<MudNavMenu Rounded="true" Margin="Margin.Dense" Color="Color.Warning" Class="pa-2" Bordered="true">
<MudNavLink Href="home" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Dashboard">داشبورد</MudNavLink>
<MudNavLink Href="orders"
Icon="@Icons.Material.Outlined.ShoppingBag">فروش</MudNavLink>
<MudNavGroup Title="محصولاتــ" Expanded="false"
Icon="@Icons.Material.Outlined.CenterFocusStrong">
<MudNavLink Href="products"
Icon="@Icons.Material.Outlined.CenterFocusStrong">محصولاتــ فروشگاه</MudNavLink>
<MudNavLink Href="product/categories"
Icon="@Icons.Material.Outlined.AllInbox">دسته بندی محصولاتـــ</MudNavLink>
<MudNavLink Href="product/brands"
Icon="@Icons.Custom.Brands.Facebook">برند محصولاتــــ</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="حسابداری" Expanded="false"
Icon="@Icons.Material.Outlined.BusinessCenter">
<MudNavLink Href="discounts"
Icon="@Icons.Material.Outlined.LocalOffer">تخفیفـــ ها</MudNavLink>
<MudNavLink Href="accounting"
Icon="@Icons.Material.Outlined.AccountBalance">گزارشاتـــ</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="باشگاه مشتریانـــ" Expanded="false"
Icon="@Icons.Material.Outlined.AccountBalance">
<MudNavLink Href="customers"
Icon="@Icons.Material.Outlined.PeopleAlt">مشترکین</MudNavLink>
<MudNavLink Href="smspanel"
Icon="@Icons.Material.Outlined.Sms">پنل پیامکی</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="وبلاگــــ" Expanded="false"
Icon="@Icons.Material.Outlined.Web">
<MudNavLink Href="blogs"
Icon="@Icons.Material.Outlined.WebStories">بلاگـــ ها</MudNavLink>
<MudNavLink Href="blog/categories"
Icon="@Icons.Material.Outlined.WebAsset">دسته بندی های بلاگـــ</MudNavLink>
</MudNavGroup>
</MudNavMenu>
</MudStack>
@code
{
private void SelectNav()
{
}
private void SelectedChange(TreeItemData? data)
{

View File

@ -4,6 +4,7 @@
@inject IPWAUpdaterService PwaUpdaterService
@inject NavigationManager NavigationManager
@inject IUserUtility UserUtility
@inject IJSRuntime Js
<style>
body .pwa-updater[b-pwa-updater] {
--pwa-updater-bar-height: 40px;
@ -34,18 +35,22 @@
<MudThemeProvider Theme="MyCustomTheme" />
<MudDialogProvider />
<MudSnackbarProvider />
<RadzenContextMenu />
<RadzenDialog />
<MudLayout>
<MudAppBar class="py-2" Color="Color.Transparent" Fixed="false" Elevation="2">
<MudHidden Breakpoint="Breakpoint.SmAndUp">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" />
</MudHidden>
<MudAvatar Size="Size.Large" Variant="Variant.Outlined">
@* <MudAvatar Size="Size.Large" Variant="Variant.Outlined">
<MudImage Src="https://img.freepik.com/free-photo/portrait-white-man-isolated_53876-40306.jpg?size=626&ext=jpg&ga=GA1.1.632798143.1705708800&semt=ais"></MudImage>
</MudAvatar>
</MudAvatar> *@
<RadzenGravatar class="w-14 h-14" Email="@_user?.Email" />
<MudStack class="mr-2" Spacing="0">
<MudText Color="Color.Inherit" Typo="Typo.body1"><b>امیرحسین خادمی</b></MudText>
<MudText Color="Color.Inherit" Typo="Typo.caption">09214802813</MudText>
<MudText Color="Color.Inherit" Typo="Typo.body1"><b>@_user?.FullName</b></MudText>
<MudText Color="Color.Inherit" Typo="Typo.caption">@_user?.PhoneNumber</MudText>
</MudStack>
<MudSpacer />
<MudIconButton Size="Size.Medium" Color="Color.Inherit" Icon="@Icons.Material.Outlined.Settings"/>
@ -115,7 +120,7 @@
};
private string _updateText = "! نسخه جدید پنل ادمین رسید";
private ApplicationUserSDto? _user;
private async Task LogoutAsync()
{
await UserUtility.LogoutAsync();
@ -130,4 +135,11 @@
base.OnInitialized();
}
protected override async Task OnInitializedAsync()
{
_user = await UserUtility.GetUserAsync();
await base.OnInitializedAsync();
}
}

View File

@ -4,7 +4,7 @@ public static class Address
{
#if DEBUG
public static string BaseAddress = "http://localhost:32770/api";
//public static string BaseAddress = "https://apinetinashop.visabartar.com/api";
//public static string BaseAddress = "https://api.vesmook.com/api";
#else
public static string BaseAddress = "https://apinetinashop.visabartar.com/api";
#endif

View File

@ -4,4 +4,5 @@ public static class LocalStorageKeys
{
public const string Token = nameof(Token);
public const string UserInfo = nameof(UserInfo);
public const string UserPermissions = nameof(UserPermissions);
}

View File

@ -1,4 +1,4 @@
@page "/brands"
@page "/product/brands"
@inject IDialogService DialogService
@inject NavigationManager NavigationManager

View File

@ -1,5 +1,5 @@
@using Radzen.Blazor
@page "/categories"
@page "/product/categories"
@inject IDialogService DialogService
@inject NavigationManager NavigationManager
@inject IRestWrapper RestWrapper

View File

@ -2,8 +2,130 @@
@page "/home"
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
<MudStack class="w-screen h-screen bg-[--color-background]">
<MudStack class="p-8 w-full h-screen bg-[--color-background]">
<MudGrid>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تعداد محصولاتــ</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-amber-600"><b>1124</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تعداد بلاگــ ها</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-blue-600"><b>845</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">فروش های امروز</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-lime-600"><b>125</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">فروش های تایید نشده</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-rose-600"><b>10</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تعداد برنـــدها</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-gray-600"><b>125</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="4" lg="2">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تعداد مشترکین</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-purple-600"><b>5632</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
</MudGrid>
<MudGrid>
<MudItem md="4">
<MudStack class="p-2">
<BaseButtonUi class="w-full rounded-md"
Icon="@Icons.Material.Outlined.AddCard"
Variant="Variant.Outlined" Color="Color.Dark"
Content="افزودن محصول جدید" />
</MudStack>
</MudItem>
<MudItem md="4">
<MudStack class="p-2">
<BaseButtonUi class="w-full rounded-md"
Icon="@Icons.Material.Outlined.AddLink"
Variant="Variant.Outlined" Color="Color.Dark"
Content="افزودن بلاگ جدید" />
</MudStack>
</MudItem>
<MudItem md="4">
<MudStack class="p-2">
<BaseButtonUi class="w-full rounded-md"
Icon="@Icons.Material.Outlined.AddBusiness"
Variant="Variant.Outlined" Color="Color.Dark"
Content="افزودن برند جدید" />
</MudStack>
</MudItem>
</MudGrid>
<MudGrid class="mt-3">
<MudItem sm="12" md="6">
<MudStack class="m-2">
<MudText Typo="Typo.h5"><b>سفارشاتــ تایید نشده</b></MudText>
<MudPaper class="rounded-md p-3" Elevation="2">
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
T="ProductSDto"
SortMode="@SortMode.None" Groupable="false">
<Columns>
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName" />
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName" />
<PropertyColumn Title="برند" Property="arg => arg.BrandNames" />
<PropertyColumn Title="قیمتــ" Property="arg => arg.Cost" />
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>
<MudStack Row="true">
<MudIconButton Icon="@Icons.Material.Filled.Edit"
Size="@Size.Small"
Variant="@Variant.Outlined"
Color="@Color.Info" />
<MudIconButton Icon="@Icons.Material.Filled.Delete"
Size="@Size.Small"
Variant="@Variant.Outlined"
Color="@Color.Error" />
</MudStack>
</CellTemplate>
</TemplateColumn>
</Columns>
<PagerContent>
<MudStack Row="true" class="w-full">
<MudPagination Rectangular="true" Variant="Variant.Filled" class="my-4 mx-auto" />
</MudStack>
</PagerContent>
</MudDataGrid>
</MudPaper>
</MudStack>
</MudItem>
<MudItem sm="12" md="6">
<MudStack class="m-2">
<MudText Typo="Typo.h5"><b>سفارشاتــ ارسال نشده</b></MudText>
<MudPaper class="rounded-md p-3" Elevation="2">
</MudPaper>
</MudStack>
</MudItem>
</MudGrid>
</MudStack>

View File

@ -72,7 +72,7 @@
<dotlottie-player src="https://lottie.host/235bcb2d-0f2c-4f06-9c36-7e6677b82e00/9tGECPkU5J.json"
background="transparent" speed="1" class="mx-auto w-64 h-64 lg:w-96 lg:h-96" loop autoplay />
<MudText Typo="Typo.h5" Align="Align.Center"><b>داشبورد تخصصی نتینا</b></MudText>
<MudText Typo="Typo.h5" Align="Align.Center"><b>داشبورد تخصصی وسمه</b></MudText>
<MudText Align="Align.Center">شما میتوانید با ورود به داشبورد تخصصی نتینا فروشگاه خود را مدیریت کنید </MudText>
</div>

View File

@ -31,6 +31,7 @@ public class LoginPageViewModel : BaseViewModel
var dto = await _restWrapper.AuthRestApi.LoginWithVerifyCodeAsync(new LoginRequestDto
{ UserName = PhoneNumber, VerifyCode = VerifyCode });
await _userUtility.SetUserAsync(dto.User);
await _userUtility.SetPermissionsAsync(dto.Permissions);
await _userUtility.SetBearerTokenAsync(dto.BearerToken);
_navigationManager.NavigateTo("home",true,true);
}

View File

@ -0,0 +1,21 @@
@using Microsoft.AspNetCore.Authorization
@attribute [AllowAnonymous]
@page "/notfound"
<div class="w-screen h-screen p-0 overflow-hidden">
<div class="h-full w-fulll">
<div class="mx-auto my-auto">
<dotlottie-player src="https://lottie.host/548178d6-2ad3-40e7-a06b-c28fa39201e4/8sDGtUyf9z.json"
background="transparent" speed="1" class="mx-auto w-96 h-96 lg:w-[38rem] lg:h-[38rem]" loop autoplay />
<MudText Typo="Typo.h2" Align="Align.Center"><h2>صفحه مورد نظر پیدا نشد</h2></MudText>
<MudText Typo="Typo.h5" Align="Align.Center">صفحه مورد نظر شما پیدا نشد یا از بین رفته است ، سریع کام بک بزن به جای قبلی جیگر </MudText>
</div>
</div>
</div>
@code {
}

View File

@ -13,6 +13,7 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await _userUtility.GetBearerTokenAsync();
if (token.IsNullOrEmpty())
{
@ -20,11 +21,17 @@ public class CustomAuthenticationStateProvider : AuthenticationStateProvider
}
var user = await _userUtility.GetUserAsync();
var identity = new ClaimsIdentity(new[]
if(user.RoleName == "Customer")
return new AuthenticationState(new());
var permissions = await _userUtility.GetPermissionsAsync();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.FirstName + " " + user.LastName),
new Claim(ClaimTypes.MobilePhone , user.PhoneNumber)
}, "Bearer");
new Claim(ClaimTypes.MobilePhone, user.PhoneNumber),
new Claim(ClaimTypes.Role,user.RoleName)
};
permissions.ForEach(p=>claims.Add(new Claim("Permission",p)));
var identity = new ClaimsIdentity(claims, "Bearer");
var claimUser = new ClaimsPrincipal(identity);

View File

@ -6,6 +6,9 @@ public interface IUserUtility
public Task SetBearerTokenAsync(string token);
public Task<ApplicationUserSDto> GetUserAsync();
public Task SetUserAsync(ApplicationUserSDto user);
public Task SetPermissionsAsync(List<string> permissions);
public Task<List<string>> GetPermissionsAsync();
public Task<bool> HasPermissionAsync(string permission);
public Task LogoutAsync();
}

View File

@ -1,4 +1,6 @@
namespace NetinaShop.AdminPanel.PWA.Utilities;
using Blazored.LocalStorage;
namespace NetinaShop.AdminPanel.PWA.Utilities;
public class UserUtility : IUserUtility
{
@ -14,10 +16,21 @@ public class UserUtility : IUserUtility
public async Task<ApplicationUserSDto> GetUserAsync() => await _localStorageService.GetItemAsync<ApplicationUserSDto>(LocalStorageKeys.UserInfo);
public async Task SetUserAsync(ApplicationUserSDto user) => await _localStorageService.SetItemAsync<ApplicationUserSDto>(LocalStorageKeys.UserInfo, user);
public async Task SetPermissionsAsync(List<string> permissions) => await _localStorageService.SetItemAsync(LocalStorageKeys.UserPermissions,permissions);
public async Task<List<string>> GetPermissionsAsync() => await _localStorageService.GetItemAsync<List<string>>(LocalStorageKeys.UserPermissions);
public async Task<bool> HasPermissionAsync(string permission)
{
var permissions = await _localStorageService.GetItemAsync<List<string>>(LocalStorageKeys.UserPermissions);
return permissions.Exists(p => p == permission);
}
public async Task LogoutAsync()
{
await _localStorageService.RemoveItemAsync(LocalStorageKeys.Token);
await _localStorageService.RemoveItemAsync(LocalStorageKeys.UserInfo);
await _localStorageService.RemoveItemAsync(LocalStorageKeys.UserPermissions);
}
//public AccessToken<ApplicationUserSDto>? AccessToken { get; set; }

View File

@ -1,11 +1,16 @@
{
"name": "NetinaShop.AdminPanel.PWA",
"name": "netina.admin.pwa",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "netina.admin.pwa",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"autoprefixer": "^10.4.17",
"flowbite": "^2.2.1",
"postcss": "^8.4.33",
"postcss-cli": "^11.0.0",
"tailwindcss": "^3.4.1"
@ -122,6 +127,15 @@
"node": ">=14"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@sindresorhus/merge-streams": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz",
@ -532,6 +546,15 @@
"node": ">=8"
}
},
"node_modules/flowbite": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.2.1.tgz",
"integrity": "sha512-iiZyBTtriEDRHrqXZgpKHaxl4B2J8HZUP8Yn1RXozUDKszWHDVj4GxQqMMB9AJHRWOgXV/4E/LJZ/zqQgBUhWA==",
"dependencies": {
"@popperjs/core": "^2.9.3",
"mini-svg-data-uri": "^1.4.3"
}
},
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
@ -826,6 +849,14 @@
"node": ">=8.6"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",

View File

@ -1,6 +1,7 @@
{
"dependencies": {
"autoprefixer": "^10.4.17",
"flowbite": "^2.2.1",
"postcss": "^8.4.33",
"postcss-cli": "^11.0.0",
"tailwindcss": "^3.4.1"

View File

@ -2,9 +2,14 @@ const colors = require('tailwindcss/colors');
const { colors: defaultColors } = require('tailwindcss/defaultTheme')
module.exports = {
plugins: [
require('flowbite/plugin')
],
darkMode: false,
content: ["./**/*.{razor,html,cshtml}"],
content: [
"./**/*.{razor,html,cshtml}",
"./node_modules/flowbite/**/*.js"
],
theme: {
fontSize: {
xs: '.75rem',

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,14 +4,13 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NetinaShop.AdminPanel.PWA</title>
<title>پنل ادمین فروشگاه</title>
<base href="/" />
<link href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" rel="stylesheet">
<link rel="stylesheet" href="css/app.css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
<link rel="stylesheet" href="css/app.min.css" />
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
<link rel="icon" type="image/png" href="favicon.png" />
<link href="NetinaShop.AdminPanel.PWA.styles.css" rel="stylesheet" />
<link href="manifest.webmanifest" rel="manifest" />
@ -22,19 +21,6 @@
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
<!-- Main Quill library -->
<script src="//cdn.quilljs.com/1.3.6/quill.js"></script>
<script src="//cdn.quilljs.com/1.3.6/quill.min.js"></script>
<!-- Theme included stylesheets -->
<link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<link href="//cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet">
<!-- Core build with no theme, formatting, non-essential modules -->
<link href="//cdn.quilljs.com/1.3.6/quill.core.css" rel="stylesheet">
<script src="//cdn.quilljs.com/1.3.6/quill.core.js"></script>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
</head>
@ -58,6 +44,7 @@
<!--<script>navigator.serviceWorker.register('service-worker.js');</script>-->
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script src="_content/Toolbelt.Blazor.PWA.Updater.Service/script.min.js"></script>
</body>
</html>

View File

@ -0,0 +1 @@