Лабораторная работа №1: интернет-магазин ТехноМаркет, ответы на контрольные вопросы
This commit is contained in:
commit
76e88091f4
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Обычные файлы и папки операционной системы
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# Результаты сборки и зависимости
|
||||
bin/
|
||||
obj/
|
||||
*.user
|
||||
.vs/
|
||||
|
||||
# Журналы приложения
|
||||
*.log
|
||||
|
||||
# Папки пакетов
|
||||
packages/
|
||||
node_modules/
|
||||
|
||||
# Файлы, которые генерирует Visual Studio при сохранении
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
123
README.md
Normal file
123
README.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# ТехноМаркет — лабораторная работа № 1
|
||||
|
||||
Проект **ASP.NET Core MVC**: запускаемый сайт с единым макетом и четырьмя
|
||||
страницами. Выполнен в рамках дисциплины «Разработка web-приложений».
|
||||
|
||||
## Автор
|
||||
|
||||
| Поле | Значение |
|
||||
|------|----------|
|
||||
| ФИО | Рыбалов Кирилл Андреевич |
|
||||
| Группа | РПО 23/1 |
|
||||
| Год | 2026 |
|
||||
| Вариант | не задан, тема выбрана самостоятельно — интернет-магазин электроники |
|
||||
|
||||
## Как запустить
|
||||
|
||||
1. Установить .NET SDK (в работе использовался SDK 10.0, проект собран под .NET 10).
|
||||
2. Открыть файл решения `TechMarket.slnx` или папку проекта `TechMarket`.
|
||||
3. Запустить проект командой:
|
||||
|
||||
```
|
||||
dotnet run --project TechMarket
|
||||
```
|
||||
|
||||
4. Открыть в браузере адрес **http://localhost:5213** (настройка из `launchSettings.json`).
|
||||
|
||||
## Страницы сайта
|
||||
|
||||
| Страница | Адрес | Что на ней |
|
||||
|----------|-------|------------|
|
||||
| Главная | `/` | описание магазина, 3 преимущества, кнопка «Перейти в каталог» |
|
||||
| Каталог | `/catalog` | 4 статичные карточки-заглушки товаров (позже — из БД) |
|
||||
| О системе | `/about` | для кого сервис и какие роли появятся |
|
||||
| Контакты | `/contacts` | адрес, телефон и форма обратной связи (с сообщением «принято» через TempData) |
|
||||
| Ошибка | `/error` | страница 404 с понятным текстом и ссылкой на главную |
|
||||
|
||||
## Что реализовано в коде
|
||||
|
||||
- маршрутизация по соглашению `/{controller}/{action}/{id?}` + атрибутные маршруты
|
||||
у страниц каталога, о системе и контактов;
|
||||
- макет `_Layout.cshtml` со шапкой, меню «Главная · Каталог · О системе · Контакты»
|
||||
и подвалом с группой, ФИО и годом;
|
||||
- `_ViewStart.cshtml` задаёт общий макет, `_ViewImports.cshtml` включает Tag Helpers;
|
||||
- форма контактов построена на Tag Helpers (`asp-controller`, `asp-action`, `asp-for`)
|
||||
с проверкой полей на стороне сервера и в браузере;
|
||||
- Bootstrap 5 подключён локально (файлы лежат в `wwwroot/lib`);
|
||||
- своя CSS-тема: акцентный цвет, стили карточек, состояния наведения;
|
||||
- светлая / тёмная тема через CSS-переменные с сохранением выбора в `localStorage`;
|
||||
- фавикон и Open Graph-теги, кастомная страница 404.
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
TechMarket/
|
||||
├── Controllers/HomeController.cs — контроллер страниц и обработки формы
|
||||
├── Models/ — модели: ошибка и форма контактов
|
||||
├── Views/
|
||||
│ ├── Home/ — страницы: Главная, Каталог, О системе, Контакты, 404
|
||||
│ └── Shared/ — макет и общие представления
|
||||
├── wwwroot/
|
||||
│ ├── css/site.css — своя тема оформления
|
||||
│ ├── js/site.js — переключатель светлой / тёмной темы
|
||||
│ └── lib/ — локальные библиотеки Bootstrap 5 и jQuery
|
||||
├── Program.cs — точка входа: сервисы и конвейер запросов
|
||||
└── appsettings.json — настройки приложения
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Контрольные вопросы
|
||||
|
||||
### 1. Чем ASP.NET Core отличается от классического ASP.NET Framework?
|
||||
|
||||
ASP.NET Core — полностью переписанный, модульный кросс-платформенный фреймворк, в то время как классический ASP.NET Framework работает только на Windows и зависит от IIS.
|
||||
|
||||
- **Кросс-платформенность:** ASP.NET Core запускается на Windows, Linux и macOS через встроенный Kestrel-сервер, не зависящий от IIS.
|
||||
- **Модульность:** каждая функция подключается как отдельный NuGet-пакет (Middleware), а не встроена в ядро.
|
||||
- **Производительность:** Kestrel оптимизирован под асинхронные сценарии и обрабатывает запросы значительно быстрее.
|
||||
- **Среда выполнения:** поддержка self-contained и framework-dependent деплоя, Docker-контейнеры, systemd-юниты.
|
||||
- **Конфигурация:** вместо web.config используется appsettings.json + environment variables.
|
||||
|
||||
### 2. Что такое middleware и в каком порядке они выполняются при обработке запроса?
|
||||
|
||||
Middleware — компоненты, образующие конвейер (pipeline), через который проходит каждый HTTP-запрос. Каждый middleware может обработать запрос, передать его дальше или вернуть ответ, не передавая дальше.
|
||||
|
||||
Типичный pipeline:
|
||||
|
||||
1. **ExceptionHandler** — перехват необработанных исключений
|
||||
2. **HSTS** — принудительное HTTPS
|
||||
3. **HttpsRedirection** — перенаправление HTTP на HTTPS
|
||||
4. **UseStaticFiles** — раздача статических файлов из `wwwroot`
|
||||
5. **Routing** — сопоставление URL с маршрутами
|
||||
6. **UseEndpoints** — вызов контроллера/действия
|
||||
|
||||
В TechMarket используется `UseStatusCodePagesWithReExecute("/Home/Error")` для перехвата кодов 404/500 и отображения пользовательской страницы ошибки.
|
||||
|
||||
### 3. Зачем нужны `_ViewStart.cshtml` и `_ViewImports.cshtml`?
|
||||
|
||||
**`_ViewStart.cshtml`** выполняется перед каждым представлением и задаёт `Layout = "_Layout"` — общий макет для всех страниц.
|
||||
|
||||
**`_ViewImports.cshtml`** подключает общие `using`-директивы и Tag Helpers:
|
||||
- `@using TechMarket` — доступ к моделям.
|
||||
- `@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers` — включение Tag Helpers.
|
||||
|
||||
### 4. Откуда берутся CSS/JS/изображения и как они подключаются через Razor?
|
||||
|
||||
Файлы хранятся в `wwwroot/` и подключаются через Razor:
|
||||
```html
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
```
|
||||
Тег `~` разрешается в корень `wwwroot`, `asp-append-version` добавляет хеш для инвалидации кеша браузера.
|
||||
|
||||
### 5. Что такое Tag Helper и почему он удобнее обычного HTML?
|
||||
|
||||
Tag Helper — серверная замена HTML-тегов с атрибутами, начинающимися с `asp-`:
|
||||
|
||||
- **Автоматическая генерация URL:** `<a asp-controller="Home" asp-action="Index">` вместо ручного прописывания пути.
|
||||
- **Валидация:** `<input asp-for="Name" />` автоматически генерирует атрибуты для клиентской валидации.
|
||||
- **Безопасность:** экранирование значений, защита от XSS.
|
||||
- **Кеш:** `asp-append-version="true"` для инвалидации кеша без написания хелпера.
|
||||
- **Читаемость:** разметка выглядит как чистый HTML с серверными атрибутами.
|
||||
3
TechMarket.slnx
Normal file
3
TechMarket.slnx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<Solution>
|
||||
<Project Path="TechMarket/TechMarket.csproj" />
|
||||
</Solution>
|
||||
59
TechMarket/Controllers/HomeController.cs
Normal file
59
TechMarket/Controllers/HomeController.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TechMarket.Models;
|
||||
|
||||
namespace TechMarket.Controllers;
|
||||
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("catalog")]
|
||||
public IActionResult Catalog()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("about")]
|
||||
public IActionResult About()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("contacts")]
|
||||
public IActionResult Contacts()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("contacts")]
|
||||
public IActionResult Contacts(ContactViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
TempData["Success"] = "Спасибо, " + model.Name + "! Ваше сообщение принято, мы скоро ответим";
|
||||
|
||||
return RedirectToAction(nameof(Contacts));
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
if (HttpContext.Response.StatusCode == 404)
|
||||
{
|
||||
return View("NotFound");
|
||||
}
|
||||
|
||||
return View(new ErrorViewModel
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
|
||||
});
|
||||
}
|
||||
}
|
||||
21
TechMarket/Models/ContactViewModel.cs
Normal file
21
TechMarket/Models/ContactViewModel.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TechMarket.Models;
|
||||
|
||||
public class ContactViewModel
|
||||
{
|
||||
[Required(ErrorMessage = "Представьтесь, пожалуйста")]
|
||||
[StringLength(100, ErrorMessage = "Имя слишком длинное")]
|
||||
[Display(Name = "Ваше имя")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[Required(ErrorMessage = "Укажите электронную почту")]
|
||||
[EmailAddress(ErrorMessage = "Похоже, e-mail написан с ошибкой")]
|
||||
[Display(Name = "E-mail")]
|
||||
public string Email { get; set; } = string.Empty;
|
||||
|
||||
[Required(ErrorMessage = "Напишите сообщение")]
|
||||
[StringLength(1000, ErrorMessage = "Сообщение слишком длинное (лимит 1000 символов)")]
|
||||
[Display(Name = "Сообщение")]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
8
TechMarket/Models/ErrorViewModel.cs
Normal file
8
TechMarket/Models/ErrorViewModel.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace TechMarket.Models;
|
||||
|
||||
public class ErrorViewModel
|
||||
{
|
||||
public string? RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
}
|
||||
28
TechMarket/Program.cs
Normal file
28
TechMarket/Program.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllersWithViews();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStatusCodePagesWithReExecute("/Home/Error");
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapStaticAssets();
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}")
|
||||
.WithStaticAssets();
|
||||
|
||||
app.Run();
|
||||
23
TechMarket/Properties/launchSettings.json
Normal file
23
TechMarket/Properties/launchSettings.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5213",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7079;http://localhost:5213",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
TechMarket/TechMarket.csproj
Normal file
9
TechMarket/TechMarket.csproj
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
51
TechMarket/Views/Home/About.cshtml
Normal file
51
TechMarket/Views/Home/About.cshtml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
@{
|
||||
ViewData["Title"] = "О системе";
|
||||
}
|
||||
|
||||
<div class="page-head">
|
||||
<h1>О системе</h1>
|
||||
<p class="text-muted">Зачем нужен ТехноМаркет и какие роли появятся в будущих лабораторных.</p>
|
||||
</div>
|
||||
|
||||
<section class="info-card info-card--wide">
|
||||
<h2 class="info-card__title">Для кого сервис</h2>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<h3 class="info-card__subtitle">Частные покупатели</h3>
|
||||
<p>Люди, которые выбирают технику для дома: ноутбук для учёбы, смартфон на замену, телевизор в гостиную.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<h3 class="info-card__subtitle">Небольшие компании</h3>
|
||||
<p>Организациям удобно закупать оргтехнику и бытовые приборы в одном месте с одним договором и счётом.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="roles-section">
|
||||
<h2 class="roles-section__title">Роли в системе</h2>
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="role-card">
|
||||
<div class="role-card__number">1</div>
|
||||
<h3 class="role-card__title">Покупатель</h3>
|
||||
<p class="role-card__text">Просматривает каталог, оставляет заявку или заказ, получает консультацию через форму обратной связи.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="role-card">
|
||||
<div class="role-card__number">2</div>
|
||||
<h3 class="role-card__title">Менеджер</h3>
|
||||
<p class="role-card__text">Принимает заявки с сайта, связывается с клиентом, оформляет заказ и следит за его доставкой.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="role-card">
|
||||
<div class="role-card__number">3</div>
|
||||
<h3 class="role-card__title">Администратор</h3>
|
||||
<p class="role-card__text">Ведёт каталог товаров, управляет заказами и учётными записями сотрудников.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
70
TechMarket/Views/Home/Catalog.cshtml
Normal file
70
TechMarket/Views/Home/Catalog.cshtml
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
@{
|
||||
ViewData["Title"] = "Каталог";
|
||||
}
|
||||
|
||||
<div class="page-head">
|
||||
<h1>Каталог</h1>
|
||||
<p class="text-muted">Здесь скоро будут товары из базы данных. Пока это статичные карточки-примеры.</p>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<article class="product-card">
|
||||
<div class="product-card__image product-card__image--laptop"></div>
|
||||
<div class="product-card__body">
|
||||
<span class="product-card__category">Ноутбук</span>
|
||||
<h3 class="product-card__title">Технобук 15</h3>
|
||||
<p class="product-card__desc">Ноутбук для учёбы и работы: 16 ГБ ОЗУ, SSD 512 ГБ, экран 15,6".</p>
|
||||
<div class="product-card__footer">
|
||||
<span class="product-card__price">79 990 ₽</span>
|
||||
<span class="product-card__badge">заглушка</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<article class="product-card">
|
||||
<div class="product-card__image product-card__image--phone"></div>
|
||||
<div class="product-card__body">
|
||||
<span class="product-card__category">Смартфоны</span>
|
||||
<h3 class="product-card__title">Технофон X</h3>
|
||||
<p class="product-card__desc">Смартфон с AMOLED-экраном 6,7", 256 ГБ памяти и тройной камерой.</p>
|
||||
<div class="product-card__footer">
|
||||
<span class="product-card__price">49 990 ₽</span>
|
||||
<span class="product-card__badge">заглушка</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<article class="product-card">
|
||||
<div class="product-card__image product-card__image--tv"></div>
|
||||
<div class="product-card__body">
|
||||
<span class="product-card__category">Телевизоры</span>
|
||||
<h3 class="product-card__title">Техновью 55</h3>
|
||||
<p class="product-card__desc">Телевизор 55" UHD 4K с голосовым пультом и Smart TV.</p>
|
||||
<div class="product-card__footer">
|
||||
<span class="product-card__price">44 990 ₽</span>
|
||||
<span class="product-card__badge">заглушка</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<article class="product-card">
|
||||
<div class="product-card__image product-card__image--headphones"></div>
|
||||
<div class="product-card__body">
|
||||
<span class="product-card__category">Наушники</span>
|
||||
<h3 class="product-card__title">Техносаунд Pro</h3>
|
||||
<p class="product-card__desc">Беспроводные наушники с шумоподавлением и зарядкой от сети 30 ч.</p>
|
||||
<div class="product-card__footer">
|
||||
<span class="product-card__price">12 990 ₽</span>
|
||||
<span class="product-card__badge">заглушка</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
62
TechMarket/Views/Home/Contacts.cshtml
Normal file
62
TechMarket/Views/Home/Contacts.cshtml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
@model ContactViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Контакты";
|
||||
}
|
||||
|
||||
<div class="page-head">
|
||||
<h1>Контакты</h1>
|
||||
<p class="text-muted">Свяжитесь с нами любым удобным способом или оставьте сообщение через форму.</p>
|
||||
</div>
|
||||
|
||||
@if (TempData["Success"] != null)
|
||||
{
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
@TempData["Success"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Закрыть"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-lg-5">
|
||||
<div class="info-card">
|
||||
<h2 class="info-card__title">Наш магазин</h2>
|
||||
<ul class="contact-list">
|
||||
<li class="contact-list__item"><span class="contact-list__icon"></span> г. Челябинск, ул. Ленина , д. 35, 2 этаж</li>
|
||||
<li class="contact-list__item"><span class="contact-list__icon"></span> <a href="tel:+79000000000">+7 (993) 930 63-58</a></li>
|
||||
<li class="contact-list__item"><span class="contact-list__icon"></span> <a href="mailto:info@techmarket.ru">info@techmarket.ru</a></li>
|
||||
<li class="contact-list__item"><span class="contact-list__icon"></span> Пн–Сб: 9:00–20:00</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-7">
|
||||
<div class="info-card">
|
||||
<h2 class="info-card__title">Обратная связь</h2>
|
||||
<form asp-controller="Home" asp-action="Contacts" method="post" class="contact-form">
|
||||
<div class="mb-3">
|
||||
<label asp-for="Name" class="form-label"></label>
|
||||
<input asp-for="Name" class="form-control" placeholder="Иван Петров" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Email" class="form-label"></label>
|
||||
<input asp-for="Email" class="form-control" placeholder="mail@example.com" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="Message" class="form-label"></label>
|
||||
<textarea asp-for="Message" class="form-control" rows="5" placeholder="Ваш вопрос, замечание или пожелание"></textarea>
|
||||
<span asp-validation-for="Message" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-accent">Отправить сообщение</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
40
TechMarket/Views/Home/Index.cshtml
Normal file
40
TechMarket/Views/Home/Index.cshtml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
@{
|
||||
ViewData["Title"] = "Главная";
|
||||
}
|
||||
|
||||
<section class="hero">
|
||||
<div class="hero__content">
|
||||
<h1 class="hero__title">ТехноМаркет</h1>
|
||||
<p class="hero__text">
|
||||
Интернет-магазин электроники и бытовой техники. Подбираем технику под любую задачу,
|
||||
привозим за 1–3 дня и даём официальную гарантию на все товары.
|
||||
</p>
|
||||
<a class="btn btn-accent btn-lg" asp-controller="Home" asp-action="Catalog">Перейти в каталог</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="row g-4 justify-content-center">
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<div class="feature-card">
|
||||
<div class="feature-card__icon"></div>
|
||||
<h3 class="feature-card__title">Быстрая доставка</h3>
|
||||
<p class="feature-card__text">Привозим заказы по всей стране: в пункт выдачи до 2 дней, курьером — от 1 дня.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<div class="feature-card">
|
||||
<div class="feature-card__icon"></div>
|
||||
<h3 class="feature-card__title">Гарантия и возврат</h3>
|
||||
<p class="feature-card__text">Официальная гарантия от производителя и возврат товара в течение 30 дней без лишних вопросов.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<div class="feature-card">
|
||||
<div class="feature-card__icon"></div>
|
||||
<h3 class="feature-card__title">Большой ассортимент</h3>
|
||||
<p class="feature-card__text">Более 5000 товаров: ноутбуки, смартфоны, телевизоры, наушники и аксессуары проверенных брендов.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
10
TechMarket/Views/Home/NotFound.cshtml
Normal file
10
TechMarket/Views/Home/NotFound.cshtml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
@{
|
||||
ViewData["Title"] = "Страница не найдена";
|
||||
}
|
||||
|
||||
<div class="error-page">
|
||||
<div class="error-page__code">404</div>
|
||||
<h1 class="error-page__title">Упс, такой страницы нет</h1>
|
||||
<p class="error-page__text">Возможно, ссылка устарела или в адресе опечатка. Попробуйте вернуться на главную.</p>
|
||||
<a class="btn btn-accent btn-lg" asp-controller="Home" asp-action="Index">Вернуться на главную</a>
|
||||
</div>
|
||||
17
TechMarket/Views/Shared/Error.cshtml
Normal file
17
TechMarket/Views/Shared/Error.cshtml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
@model ErrorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Ошибка";
|
||||
}
|
||||
|
||||
<div class="error-page">
|
||||
<div class="error-page__code">:(</div>
|
||||
<h1 class="error-page__title">Что-то пошло не так</h1>
|
||||
<p class="error-page__text">Произошла внутренняя ошибка. Мы уже в курсе, попробуйте обновить страницу чуть позже.</p>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p class="error-page__request">Номер запроса: <code>@Model.RequestId</code></p>
|
||||
}
|
||||
|
||||
<a class="btn btn-accent btn-lg" asp-controller="Home" asp-action="Index">Вернуться на главную</a>
|
||||
</div>
|
||||
103
TechMarket/Views/Shared/_Layout.cshtml
Normal file
103
TechMarket/Views/Shared/_Layout.cshtml
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
@{
|
||||
var currentAction = ViewContext.RouteData.Values["action"]?.ToString();
|
||||
var currentController = ViewContext.RouteData.Values["controller"]?.ToString();
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>@ViewData["Title"] - ТехноМаркет</title>
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="~/favicon.svg" />
|
||||
|
||||
<meta property="og:title" content="ТехноМаркет — интернет-магазин электроники" />
|
||||
<meta property="og:description" content="Покупайте технику и электронику с гарантией и быстрой доставкой по всей стране." />
|
||||
<meta property="og:type" content="website" />
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var theme = localStorage.getItem('techmarket-theme');
|
||||
if (!theme) {
|
||||
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark site-navbar">
|
||||
<div class="container">
|
||||
<a class="navbar-brand brand" asp-controller="Home" asp-action="Index">
|
||||
<span class="brand-mark">Т</span> ТехноМаркет
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#mainMenu"
|
||||
aria-controls="mainMenu" aria-expanded="false"
|
||||
aria-label="Переключить меню">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="mainMenu">
|
||||
<ul class="navbar-nav ms-auto align-items-lg-center">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @(currentAction == "Index" && currentController == "Home" ? "active" : "")"
|
||||
asp-controller="Home" asp-action="Index">Главная</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @(currentAction == "Catalog" ? "active" : "")"
|
||||
asp-controller="Home" asp-action="Catalog">Каталог</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @(currentAction == "About" ? "active" : "")"
|
||||
asp-controller="Home" asp-action="About">О системе</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @(currentAction == "Contacts" ? "active" : "")"
|
||||
asp-controller="Home" asp-action="Contacts">Контакты</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<button type="button" class="btn theme-toggle" id="themeToggle"
|
||||
aria-label="Переключить светлую и тёмную тему">
|
||||
<svg class="icon-moon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 3a9 9 0 1 0 9 9c0-.46-.04-.92-.1-1.36a5.39 5.39 0 0 1-4.4 2.26 5.4 5.4 0 0 1-3.14-9.8c-.44-.06-.9-.1-1.36-.1z" />
|
||||
</svg>
|
||||
<svg class="icon-sun" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
<path d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="page-main">
|
||||
<div class="container">
|
||||
@RenderBody()
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<span class="site-footer__project">ТехноМаркет — учебный проект</span>
|
||||
<span class="site-footer__author">Группа РПО 23/1 · Рыбалов Кирилл Андреевич · 2026</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
2
TechMarket/Views/Shared/_ValidationScriptsPartial.cshtml
Normal file
2
TechMarket/Views/Shared/_ValidationScriptsPartial.cshtml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>
|
||||
3
TechMarket/Views/_ViewImports.cshtml
Normal file
3
TechMarket/Views/_ViewImports.cshtml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@using TechMarket
|
||||
@using TechMarket.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
3
TechMarket/Views/_ViewStart.cshtml
Normal file
3
TechMarket/Views/_ViewStart.cshtml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
8
TechMarket/appsettings.Development.json
Normal file
8
TechMarket/appsettings.Development.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
TechMarket/appsettings.json
Normal file
9
TechMarket/appsettings.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
506
TechMarket/wwwroot/css/site.css
Normal file
506
TechMarket/wwwroot/css/site.css
Normal file
|
|
@ -0,0 +1,506 @@
|
|||
:root {
|
||||
--accent: #10b981;
|
||||
--accent-dark: #059669;
|
||||
--accent-soft: rgba(16, 185, 129, 0.14);
|
||||
--accent-glow: rgba(52, 211, 153, 0.22);
|
||||
--bg-body: #f2f8f5;
|
||||
--bg-surface: #ffffff;
|
||||
--bg-nav: #083525;
|
||||
--text-main: #16291f;
|
||||
--text-muted: #5c7268;
|
||||
--border: #def0e7;
|
||||
--shadow: 0 6px 18px rgba(14, 65, 44, 0.08);
|
||||
--shadow-hover: 0 14px 30px rgba(14, 65, 44, 0.16);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--accent: #34d399;
|
||||
--accent-dark: #10b981;
|
||||
--accent-soft: rgba(52, 211, 153, 0.18);
|
||||
--accent-glow: rgba(52, 211, 153, 0.28);
|
||||
--bg-body: #081310;
|
||||
--bg-surface: #10201a;
|
||||
--bg-nav: #05130e;
|
||||
--text-main: #dff7ec;
|
||||
--text-muted: #8fb3a3;
|
||||
--border: #22443a;
|
||||
--shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
|
||||
--shadow-hover: 0 14px 30px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg-body);
|
||||
color: var(--text-main);
|
||||
font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.site-navbar {
|
||||
background: var(--bg-nav);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.brand-mark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 10px;
|
||||
background: var(--accent);
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.site-navbar .nav-link {
|
||||
color: #cfe0f3;
|
||||
padding: 0.6rem 1rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.site-navbar .nav-link.active {
|
||||
color: #ffffff;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.site-navbar .nav-link:hover:not(.active) {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
color: #cfe0f3;
|
||||
background: transparent;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
color: #ffffff;
|
||||
transform: rotate(20deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.theme-toggle.is-dark .icon-sun {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.theme-toggle.is-dark .icon-moon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.theme-toggle .icon-sun {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-main {
|
||||
flex: 1 0 auto;
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.page-head {
|
||||
margin-bottom: 1.8rem;
|
||||
}
|
||||
|
||||
.page-head h1 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #083525 0%, var(--accent) 130%);
|
||||
border-radius: 18px;
|
||||
padding: 3.4rem 2rem;
|
||||
color: #ffffff;
|
||||
box-shadow: var(--shadow);
|
||||
margin-bottom: 2.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 360px;
|
||||
height: 360px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, var(--accent-glow), transparent 70%);
|
||||
top: -150px;
|
||||
right: -120px;
|
||||
pointer-events: none;
|
||||
animation: heroGlow 5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes heroGlow {
|
||||
0%, 100% { opacity: 0.7; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.hero__content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero__title {
|
||||
font-size: 2.6rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.hero__text {
|
||||
max-width: 620px;
|
||||
margin: 0 auto 1.6rem;
|
||||
font-size: 1.15rem;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.btn-accent {
|
||||
background: linear-gradient(135deg, #16a34a 0%, #059669 100%);
|
||||
border: 1px solid transparent;
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
padding: 0.6rem 1.6rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-accent:hover {
|
||||
background: linear-gradient(135deg, #15803d 0%, #047857 100%);
|
||||
color: #ffffff;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 1.8rem 1.4rem;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
box-shadow: var(--shadow);
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-6px);
|
||||
border-color: var(--accent);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.feature-card__icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0 auto 1rem;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-soft);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
|
||||
.feature-card__title {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: var(--shadow);
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-6px);
|
||||
border-color: var(--accent);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.product-card__image {
|
||||
height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 3.2rem;
|
||||
}
|
||||
|
||||
.product-card__image--laptop {
|
||||
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
|
||||
}
|
||||
|
||||
.product-card__image--phone {
|
||||
background: linear-gradient(135deg, #ccfbf1, #99f6e4);
|
||||
}
|
||||
|
||||
.product-card__image--tv {
|
||||
background: linear-gradient(135deg, #ecfccb, #d9f99d);
|
||||
}
|
||||
|
||||
.product-card__image--headphones {
|
||||
background: linear-gradient(135deg, #dcfce7, #bbf7d0);
|
||||
}
|
||||
|
||||
.product-card__body {
|
||||
padding: 1.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.product-card__category {
|
||||
color: var(--accent);
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.product-card__title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.product-card__desc {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.92rem;
|
||||
flex: 1 1 auto;
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
.product-card__footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.product-card__price {
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.product-card__badge {
|
||||
font-size: 0.72rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.4px;
|
||||
color: var(--text-muted);
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 1.6rem;
|
||||
box-shadow: var(--shadow);
|
||||
height: 100%;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.info-card:hover {
|
||||
border-color: var(--accent);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.info-card__title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.info-card__subtitle {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.contact-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.contact-list__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.45rem 0;
|
||||
}
|
||||
|
||||
.contact-list__icon {
|
||||
margin-right: 0.7rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.contact-list__item a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contact-list__item a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.contact-form .form-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.contact-form .form-control {
|
||||
background: var(--bg-body);
|
||||
border-color: var(--border);
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.contact-form .form-control:focus {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 0.2rem var(--accent-soft);
|
||||
}
|
||||
|
||||
.contact-form .form-control::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.roles-section {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.roles-section__title {
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.4rem;
|
||||
}
|
||||
|
||||
.role-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 1.6rem;
|
||||
height: 100%;
|
||||
box-shadow: var(--shadow);
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.role-card:hover {
|
||||
transform: translateY(-6px);
|
||||
border-color: var(--accent);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.role-card__number {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.role-card__title {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.role-card__text {
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.error-page {
|
||||
text-align: center;
|
||||
padding: 4rem 1rem;
|
||||
}
|
||||
|
||||
.error-page__code {
|
||||
font-size: 5.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
line-height: 1;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.error-page__title {
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.error-page__text {
|
||||
color: var(--text-muted);
|
||||
max-width: 480px;
|
||||
margin: 0 auto 1.5rem;
|
||||
}
|
||||
|
||||
.error-page__request {
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
background: var(--bg-nav);
|
||||
color: #aebfd4;
|
||||
padding: 1.2rem 0;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.site-footer .container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.site-footer__project {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.site-footer__author {
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.hero {
|
||||
padding: 2.2rem 1.2rem;
|
||||
margin-bottom: 1.8rem;
|
||||
}
|
||||
|
||||
.hero__title {
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
|
||||
.hero__text {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.error-page__code {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.site-footer .container {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
BIN
TechMarket/wwwroot/favicon.ico
Normal file
BIN
TechMarket/wwwroot/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
4
TechMarket/wwwroot/favicon.svg
Normal file
4
TechMarket/wwwroot/favicon.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<rect x="2" y="2" width="60" height="60" rx="14" fill="#10b981" />
|
||||
<text x="32" y="45" font-family="Arial, sans-serif" font-size="40" font-weight="bold" text-anchor="middle" fill="#ffffff">Т</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 270 B |
15
TechMarket/wwwroot/js/site.js
Normal file
15
TechMarket/wwwroot/js/site.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const themeToggleButton = document.getElementById('themeToggle');
|
||||
|
||||
function applyTheme(themeName) {
|
||||
document.documentElement.setAttribute('data-theme', themeName);
|
||||
themeToggleButton.classList.toggle('is-dark', themeName === 'dark');
|
||||
}
|
||||
|
||||
themeToggleButton.addEventListener('click', function () {
|
||||
const current = document.documentElement.getAttribute('data-theme');
|
||||
const next = current === 'dark' ? 'light' : 'dark';
|
||||
localStorage.setItem('techmarket-theme', next);
|
||||
applyTheme(next);
|
||||
});
|
||||
|
||||
applyTheme(document.documentElement.getAttribute('data-theme'));
|
||||
22
TechMarket/wwwroot/lib/bootstrap/LICENSE
Normal file
22
TechMarket/wwwroot/lib/bootstrap/LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2021 Twitter, Inc.
|
||||
Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
4085
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
4085
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4084
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css
vendored
Normal file
4084
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
597
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
597
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
/*!
|
||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
594
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css
vendored
Normal file
594
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css
vendored
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
/*!
|
||||
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5402
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css
vendored
Normal file
5402
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5393
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css
vendored
Normal file
5393
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
12057
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
12057
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
12030
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css
vendored
Normal file
12030
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css
vendored
Normal file
6
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6314
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
6314
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4447
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js
vendored
Normal file
4447
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js
vendored
Normal file
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4494
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
4494
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
7
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
1
TechMarket/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,23 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) .NET Foundation and Contributors
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
435
TechMarket/wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js
vendored
Normal file
435
TechMarket/wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js
vendored
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/**
|
||||
* @license
|
||||
* Unobtrusive validation support library for jQuery and jQuery Validate
|
||||
* Copyright (c) .NET Foundation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
* @version v4.0.0
|
||||
*/
|
||||
|
||||
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
|
||||
/*global document: false, jQuery: false */
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// CommonJS-like environments that support module.exports
|
||||
module.exports = factory(require('jquery-validation'));
|
||||
} else {
|
||||
// Browser global
|
||||
jQuery.validator.unobtrusive = factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
var $jQval = $.validator,
|
||||
adapters,
|
||||
data_validation = "unobtrusiveValidation";
|
||||
|
||||
function setValidationValues(options, ruleName, value) {
|
||||
options.rules[ruleName] = value;
|
||||
if (options.message) {
|
||||
options.messages[ruleName] = options.message;
|
||||
}
|
||||
}
|
||||
|
||||
function splitAndTrim(value) {
|
||||
return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
|
||||
}
|
||||
|
||||
function escapeAttributeValue(value) {
|
||||
// As mentioned on http://api.jquery.com/category/selectors/
|
||||
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
|
||||
}
|
||||
|
||||
function getModelPrefix(fieldName) {
|
||||
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
function appendModelPrefix(value, prefix) {
|
||||
if (value.indexOf("*.") === 0) {
|
||||
value = value.replace("*.", prefix);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function onError(error, inputElement) { // 'this' is the form element
|
||||
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
|
||||
replaceAttrValue = container.attr("data-valmsg-replace"),
|
||||
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
|
||||
|
||||
container.removeClass("field-validation-valid").addClass("field-validation-error");
|
||||
error.data("unobtrusiveContainer", container);
|
||||
|
||||
if (replace) {
|
||||
container.empty();
|
||||
error.removeClass("input-validation-error").appendTo(container);
|
||||
}
|
||||
else {
|
||||
error.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function onErrors(event, validator) { // 'this' is the form element
|
||||
var container = $(this).find("[data-valmsg-summary=true]"),
|
||||
list = container.find("ul");
|
||||
|
||||
if (list && list.length && validator.errorList.length) {
|
||||
list.empty();
|
||||
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
|
||||
|
||||
$.each(validator.errorList, function () {
|
||||
$("<li />").html(this.message).appendTo(list);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onSuccess(error) { // 'this' is the form element
|
||||
var container = error.data("unobtrusiveContainer");
|
||||
|
||||
if (container) {
|
||||
var replaceAttrValue = container.attr("data-valmsg-replace"),
|
||||
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
|
||||
|
||||
container.addClass("field-validation-valid").removeClass("field-validation-error");
|
||||
error.removeData("unobtrusiveContainer");
|
||||
|
||||
if (replace) {
|
||||
container.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onReset(event) { // 'this' is the form element
|
||||
var $form = $(this),
|
||||
key = '__jquery_unobtrusive_validation_form_reset';
|
||||
if ($form.data(key)) {
|
||||
return;
|
||||
}
|
||||
// Set a flag that indicates we're currently resetting the form.
|
||||
$form.data(key, true);
|
||||
try {
|
||||
$form.data("validator").resetForm();
|
||||
} finally {
|
||||
$form.removeData(key);
|
||||
}
|
||||
|
||||
$form.find(".validation-summary-errors")
|
||||
.addClass("validation-summary-valid")
|
||||
.removeClass("validation-summary-errors");
|
||||
$form.find(".field-validation-error")
|
||||
.addClass("field-validation-valid")
|
||||
.removeClass("field-validation-error")
|
||||
.removeData("unobtrusiveContainer")
|
||||
.find(">*") // If we were using valmsg-replace, get the underlying error
|
||||
.removeData("unobtrusiveContainer");
|
||||
}
|
||||
|
||||
function validationInfo(form) {
|
||||
var $form = $(form),
|
||||
result = $form.data(data_validation),
|
||||
onResetProxy = $.proxy(onReset, form),
|
||||
defaultOptions = $jQval.unobtrusive.options || {},
|
||||
execInContext = function (name, args) {
|
||||
var func = defaultOptions[name];
|
||||
func && $.isFunction(func) && func.apply(form, args);
|
||||
};
|
||||
|
||||
if (!result) {
|
||||
result = {
|
||||
options: { // options structure passed to jQuery Validate's validate() method
|
||||
errorClass: defaultOptions.errorClass || "input-validation-error",
|
||||
errorElement: defaultOptions.errorElement || "span",
|
||||
errorPlacement: function () {
|
||||
onError.apply(form, arguments);
|
||||
execInContext("errorPlacement", arguments);
|
||||
},
|
||||
invalidHandler: function () {
|
||||
onErrors.apply(form, arguments);
|
||||
execInContext("invalidHandler", arguments);
|
||||
},
|
||||
messages: {},
|
||||
rules: {},
|
||||
success: function () {
|
||||
onSuccess.apply(form, arguments);
|
||||
execInContext("success", arguments);
|
||||
}
|
||||
},
|
||||
attachValidation: function () {
|
||||
$form
|
||||
.off("reset." + data_validation, onResetProxy)
|
||||
.on("reset." + data_validation, onResetProxy)
|
||||
.validate(this.options);
|
||||
},
|
||||
validate: function () { // a validation function that is called by unobtrusive Ajax
|
||||
$form.validate();
|
||||
return $form.valid();
|
||||
}
|
||||
};
|
||||
$form.data(data_validation, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
$jQval.unobtrusive = {
|
||||
adapters: [],
|
||||
|
||||
parseElement: function (element, skipAttach) {
|
||||
/// <summary>
|
||||
/// Parses a single HTML element for unobtrusive validation attributes.
|
||||
/// </summary>
|
||||
/// <param name="element" domElement="true">The HTML element to be parsed.</param>
|
||||
/// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
|
||||
/// validation to the form. If parsing just this single element, you should specify true.
|
||||
/// If parsing several elements, you should specify false, and manually attach the validation
|
||||
/// to the form when you are finished. The default is false.</param>
|
||||
var $element = $(element),
|
||||
form = $element.parents("form")[0],
|
||||
valInfo, rules, messages;
|
||||
|
||||
if (!form) { // Cannot do client-side validation without a form
|
||||
return;
|
||||
}
|
||||
|
||||
valInfo = validationInfo(form);
|
||||
valInfo.options.rules[element.name] = rules = {};
|
||||
valInfo.options.messages[element.name] = messages = {};
|
||||
|
||||
$.each(this.adapters, function () {
|
||||
var prefix = "data-val-" + this.name,
|
||||
message = $element.attr(prefix),
|
||||
paramValues = {};
|
||||
|
||||
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
|
||||
prefix += "-";
|
||||
|
||||
$.each(this.params, function () {
|
||||
paramValues[this] = $element.attr(prefix + this);
|
||||
});
|
||||
|
||||
this.adapt({
|
||||
element: element,
|
||||
form: form,
|
||||
message: message,
|
||||
params: paramValues,
|
||||
rules: rules,
|
||||
messages: messages
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(rules, { "__dummy__": true });
|
||||
|
||||
if (!skipAttach) {
|
||||
valInfo.attachValidation();
|
||||
}
|
||||
},
|
||||
|
||||
parse: function (selector) {
|
||||
/// <summary>
|
||||
/// Parses all the HTML elements in the specified selector. It looks for input elements decorated
|
||||
/// with the [data-val=true] attribute value and enables validation according to the data-val-*
|
||||
/// attribute values.
|
||||
/// </summary>
|
||||
/// <param name="selector" type="String">Any valid jQuery selector.</param>
|
||||
|
||||
// $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
|
||||
// element with data-val=true
|
||||
var $selector = $(selector),
|
||||
$forms = $selector.parents()
|
||||
.addBack()
|
||||
.filter("form")
|
||||
.add($selector.find("form"))
|
||||
.has("[data-val=true]");
|
||||
|
||||
$selector.find("[data-val=true]").each(function () {
|
||||
$jQval.unobtrusive.parseElement(this, true);
|
||||
});
|
||||
|
||||
$forms.each(function () {
|
||||
var info = validationInfo(this);
|
||||
if (info) {
|
||||
info.attachValidation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
adapters = $jQval.unobtrusive.adapters;
|
||||
|
||||
adapters.add = function (adapterName, params, fn) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
|
||||
/// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
|
||||
/// mmmm is the parameter name).</param>
|
||||
/// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
|
||||
/// attributes into jQuery Validate rules and/or messages.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
if (!fn) { // Called with no params, just a function
|
||||
fn = params;
|
||||
params = [];
|
||||
}
|
||||
this.push({ name: adapterName, params: params, adapt: fn });
|
||||
return this;
|
||||
};
|
||||
|
||||
adapters.addBool = function (adapterName, ruleName) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation rule has no parameter values.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
/// of adapterName will be used instead.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, function (options) {
|
||||
setValidationValues(options, ruleName || adapterName, true);
|
||||
});
|
||||
};
|
||||
|
||||
adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
|
||||
/// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
/// have a minimum value.</param>
|
||||
/// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
/// have a maximum value.</param>
|
||||
/// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
|
||||
/// have both a minimum and maximum value.</param>
|
||||
/// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
/// contains the minimum value. The default is "min".</param>
|
||||
/// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
/// contains the maximum value. The default is "max".</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
|
||||
var min = options.params.min,
|
||||
max = options.params.max;
|
||||
|
||||
if (min && max) {
|
||||
setValidationValues(options, minMaxRuleName, [min, max]);
|
||||
}
|
||||
else if (min) {
|
||||
setValidationValues(options, minRuleName, min);
|
||||
}
|
||||
else if (max) {
|
||||
setValidationValues(options, maxRuleName, max);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
adapters.addSingleVal = function (adapterName, attribute, ruleName) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation rule has a single value.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
|
||||
/// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
|
||||
/// The default is "val".</param>
|
||||
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
/// of adapterName will be used instead.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, [attribute || "val"], function (options) {
|
||||
setValidationValues(options, ruleName || adapterName, options.params[attribute]);
|
||||
});
|
||||
};
|
||||
|
||||
$jQval.addMethod("__dummy__", function (value, element, params) {
|
||||
return true;
|
||||
});
|
||||
|
||||
$jQval.addMethod("regex", function (value, element, params) {
|
||||
var match;
|
||||
if (this.optional(element)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
match = new RegExp(params).exec(value);
|
||||
return (match && (match.index === 0) && (match[0].length === value.length));
|
||||
});
|
||||
|
||||
$jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
|
||||
var match;
|
||||
if (nonalphamin) {
|
||||
match = value.match(/\W/g);
|
||||
match = match && match.length >= nonalphamin;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
if ($jQval.methods.extension) {
|
||||
adapters.addSingleVal("accept", "mimtype");
|
||||
adapters.addSingleVal("extension", "extension");
|
||||
} else {
|
||||
// for backward compatibility, when the 'extension' validation method does not exist, such as with versions
|
||||
// of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
|
||||
// validating the extension, and ignore mime-type validations as they are not supported.
|
||||
adapters.addSingleVal("extension", "extension", "accept");
|
||||
}
|
||||
|
||||
adapters.addSingleVal("regex", "pattern");
|
||||
adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
|
||||
adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
|
||||
adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
|
||||
adapters.add("equalto", ["other"], function (options) {
|
||||
var prefix = getModelPrefix(options.element.name),
|
||||
other = options.params.other,
|
||||
fullOtherName = appendModelPrefix(other, prefix),
|
||||
element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
|
||||
|
||||
setValidationValues(options, "equalTo", element);
|
||||
});
|
||||
adapters.add("required", function (options) {
|
||||
// jQuery Validate equates "required" with "mandatory" for checkbox elements
|
||||
if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
|
||||
setValidationValues(options, "required", true);
|
||||
}
|
||||
});
|
||||
adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
|
||||
var value = {
|
||||
url: options.params.url,
|
||||
type: options.params.type || "GET",
|
||||
data: {}
|
||||
},
|
||||
prefix = getModelPrefix(options.element.name);
|
||||
|
||||
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
|
||||
var paramName = appendModelPrefix(fieldName, prefix);
|
||||
value.data[paramName] = function () {
|
||||
var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
|
||||
// For checkboxes and radio buttons, only pick up values from checked fields.
|
||||
if (field.is(":checkbox")) {
|
||||
return field.filter(":checked").val() || field.filter(":hidden").val() || '';
|
||||
}
|
||||
else if (field.is(":radio")) {
|
||||
return field.filter(":checked").val() || '';
|
||||
}
|
||||
return field.val();
|
||||
};
|
||||
});
|
||||
|
||||
setValidationValues(options, "remote", value);
|
||||
});
|
||||
adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
|
||||
if (options.params.min) {
|
||||
setValidationValues(options, "minlength", options.params.min);
|
||||
}
|
||||
if (options.params.nonalphamin) {
|
||||
setValidationValues(options, "nonalphamin", options.params.nonalphamin);
|
||||
}
|
||||
if (options.params.regex) {
|
||||
setValidationValues(options, "regex", options.params.regex);
|
||||
}
|
||||
});
|
||||
adapters.add("fileextensions", ["extensions"], function (options) {
|
||||
setValidationValues(options, "extension", options.params.extensions);
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$jQval.unobtrusive.parse(document);
|
||||
});
|
||||
|
||||
return $jQval.unobtrusive;
|
||||
}));
|
||||
8
TechMarket/wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js
vendored
Normal file
8
TechMarket/wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
22
TechMarket/wwwroot/lib/jquery-validation/LICENSE.md
Normal file
22
TechMarket/wwwroot/lib/jquery-validation/LICENSE.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright Jörn Zaefferer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
1505
TechMarket/wwwroot/lib/jquery-validation/dist/additional-methods.js
vendored
Normal file
1505
TechMarket/wwwroot/lib/jquery-validation/dist/additional-methods.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
TechMarket/wwwroot/lib/jquery-validation/dist/additional-methods.min.js
vendored
Normal file
4
TechMarket/wwwroot/lib/jquery-validation/dist/additional-methods.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1703
TechMarket/wwwroot/lib/jquery-validation/dist/jquery.validate.js
vendored
Normal file
1703
TechMarket/wwwroot/lib/jquery-validation/dist/jquery.validate.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
TechMarket/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js
vendored
Normal file
4
TechMarket/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
21
TechMarket/wwwroot/lib/jquery/LICENSE.txt
Normal file
21
TechMarket/wwwroot/lib/jquery/LICENSE.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
10716
TechMarket/wwwroot/lib/jquery/dist/jquery.js
vendored
Normal file
10716
TechMarket/wwwroot/lib/jquery/dist/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
TechMarket/wwwroot/lib/jquery/dist/jquery.min.js
vendored
Normal file
2
TechMarket/wwwroot/lib/jquery/dist/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/jquery/dist/jquery.min.map
vendored
Normal file
1
TechMarket/wwwroot/lib/jquery/dist/jquery.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8617
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.js
vendored
Normal file
8617
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.min.js
vendored
Normal file
2
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.min.map
vendored
Normal file
1
TechMarket/wwwroot/lib/jquery/dist/jquery.slim.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user