merge to master
|
|
@ -67,10 +67,10 @@ public static class TiamConstClient
|
|||
};
|
||||
|
||||
#if RELEASE
|
||||
public static string SystemEmailAddress = "system@touriam.com";
|
||||
public static string SystemEmailAddress = "test@touriam.com";
|
||||
public static LogLevel DefaultLogLevelClient = LogLevel.Debug;
|
||||
#else
|
||||
public static string SystemEmailAddress = "system@anataworld.com";
|
||||
public static string SystemEmailAddress = "test@touriam.com";
|
||||
public static LogLevel DefaultLogLevelClient = LogLevel.Detail;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
public enum SeatNumberPriceType : byte
|
||||
{
|
||||
Price1SeatNum = 0,
|
||||
Price2SeatNum = 4,
|
||||
Price3SeatNum = 8,
|
||||
Price2SeatNum = 5,
|
||||
Price3SeatNum = 7,
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ using AyCode.Core.Extensions;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TIAM.Entities.ServiceProviders;
|
||||
using TIAM.Entities.Addresses;
|
||||
using DevExpress.Pdf.Native.BouncyCastle.Asn1.Ocsp;
|
||||
//using DevExpress.Pdf.Native.BouncyCastle.Asn1.Ocsp;
|
||||
|
||||
namespace TIAM.Database.Test
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ using AyCode.Interfaces.Entities;
|
|||
using TIAM.Models;
|
||||
using TIAM.Models.Dtos.Users;
|
||||
using TIAM.Models.PageViewModels;
|
||||
using EmailMessage = TIAM.Entities.Emails.EmailMessage;
|
||||
|
||||
namespace TIAM.Database.DataLayers.Admins
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using TIAM.Entities.ServiceProviders;
|
|||
using TIAM.Entities.Users;
|
||||
using TIAM.Models;
|
||||
using TIAM.Models.Dtos.Users;
|
||||
using EmailMessage = TIAM.Entities.Emails.EmailMessage;
|
||||
|
||||
namespace TIAM.Database.DataLayers.Users
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,11 +10,32 @@ namespace TIAM.Database.DbSets.Transfers;
|
|||
public static class TransferToDriverDbSetExtensions
|
||||
{
|
||||
#region TransferToDriver
|
||||
|
||||
public static TransferToDriver? GetTransferToDriverById(this ITransferToDriverDbSet ctx, Guid transferToDriverId, bool autoInclude = true)
|
||||
=> ctx.TransferToDrivers.FirstOrDefault(x => x.Id == transferToDriverId);
|
||||
=> ctx.TransferToDrivers
|
||||
.Where(x => x.Id == transferToDriverId)
|
||||
.Include(x => x.UserProductMapping.User.Products).ThenInclude(x => x.UserProductMappings)
|
||||
.Include(x => x.Car.UserProductMapping.Product.ServiceProvider).ThenInclude(x => x.Products)
|
||||
.Include(x => x.UserProductMapping.User.Profile.Address)
|
||||
.Include(x => x.Transfer)
|
||||
.FirstOrDefault(x => x.Id == transferToDriverId);
|
||||
|
||||
public static IQueryable<TransferToDriver> GetTransferToDriversByTransferId(this ITransferToDriverDbSet ctx, Guid transferId, bool autoInclude = true)
|
||||
=> ctx.TransferToDrivers.Where(x => x.TransferId == transferId);
|
||||
=> ctx.TransferToDrivers
|
||||
.Where(x => x.TransferId == transferId)
|
||||
.Include(x => x.Car.UserProductMapping.Product.ServiceProvider).ThenInclude(x => x.Products)
|
||||
.Include(x => x.UserProductMapping.User.Profile.Address)
|
||||
.Include(x => x.Transfer);
|
||||
|
||||
//.Include(x => x.UserProductMapping.User.Products).ThenInclude(x => x.UserProductMappings)
|
||||
//.Include(x => x.Car.UserProductMapping.Product.ServiceProvider).ThenInclude(x => x.Products)
|
||||
//.Include(x => x.UserProductMapping.User.Profile.Address)
|
||||
//.Include(x => x.Transfer);
|
||||
|
||||
//.Include(x => x.UserProductMapping.User.Products).ThenInclude(x => x.UserProductMappings).ThenInclude(x => x.User.Profile.Address)
|
||||
//.Include(x => x.Car.UserProductMapping.Product.ServiceProvider).ThenInclude(x => x.Products)
|
||||
//.Include(x => x.UserProductMapping.User.Profile.Address)
|
||||
//.Include(x => x.Transfer);
|
||||
|
||||
public static IQueryable<TransferToDriver> GetTransferToDriversByUpmId(this ITransferToDriverDbSet ctx, Guid upmId, bool autoInclude = true)
|
||||
=> ctx.TransferToDrivers.Where(x => x.UserProductMappingId == upmId);
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="24.1.3" />
|
||||
<PackageReference Include="DevExpress.Data" Version="24.2.3" />
|
||||
<PackageReference Include="MessagePack.Annotations" Version="2.5.187" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="24.2.3" />
|
||||
<PackageReference Include="MessagePack.Annotations" Version="2.5.187" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DataLayers\DTOs\" />
|
||||
<Folder Include="DataLayers\Permissions\" />
|
||||
<Folder Include="DataLayers\Products\" />
|
||||
<Folder Include="DbSets\Addresses\" />
|
||||
<Folder Include="Extensions\" />
|
||||
<Folder Include="ModelBuilders\Emails\" />
|
||||
<Folder Include="ModelBuilders\Profiles\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TIAM.Core\TIAM.Core.csproj" />
|
||||
<ProjectReference Include="..\TIAM.Entities.Server\TIAM.Entities.Server.csproj" />
|
||||
<ProjectReference Include="..\TIAM.Entities\TIAM.Entities.csproj" />
|
||||
<ProjectReference Include="..\TIAM.Models\TIAM.Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="AyCode.Core">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Core.Server">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Core.Server.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Database">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Database.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Entities">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Entities.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Entities.Server">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Entities.Server.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Interfaces">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Interfaces.Server">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Interfaces.Server.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Models">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Models.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Models.Server">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Models.Server.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AyCode.Utils">
|
||||
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\Debug\net8.0\AyCode.Utils.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -6,6 +6,10 @@
|
|||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="24.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TIAM.Core\TIAM.Core.csproj" />
|
||||
<ProjectReference Include="..\TIAM.Entities.Server\TIAM.Entities.Server.csproj" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using AyCode.Blazor.Models.ViewModels;
|
||||
using TIAM.Entities.Emails;
|
||||
using TIAM.Models.PageViewModels;
|
||||
using EmailMessage = TIAM.Entities.Emails.EmailMessage;
|
||||
|
||||
namespace TIAM.Models;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
<Folder Include="GridViewModels\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="24.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Aycode.Blazor\AyCode.Blazor.Components\AyCode.Blazor.Components.csproj" />
|
||||
<ProjectReference Include="..\..\Aycode.Blazor\AyCode.Blazor.Models\AyCode.Blazor.Models.csproj" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DeveloperDbConnection":
|
||||
"Data Source=185.51.190.197;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=Anata_Development_Team;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
"DeveloperDbConnection": "Data Source=195.26.231.218;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=sa;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using AyCode.Core.Helpers;
|
||||
using AyCode.Models.Enums;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
@ -13,6 +14,11 @@ namespace TIAM.Services.Server
|
|||
{
|
||||
public class MessageSenderService(IConfiguration configuration, AdminDal adminDal) : IMessageSenderService
|
||||
{
|
||||
private readonly string smtpHost = "smtp.rackhost.hu";
|
||||
private readonly int smtpPort = 587; // Change if needed
|
||||
private readonly string smtpUser = "system@touriam.com";
|
||||
private readonly string smtpPass = "Villany1";
|
||||
|
||||
public async Task<string> SendMessageAsync(EmailMessage message, int messageType)
|
||||
{
|
||||
var result = "";
|
||||
|
|
@ -24,7 +30,8 @@ namespace TIAM.Services.Server
|
|||
//var subject = emailMessage.Subject;
|
||||
|
||||
//adminDal.AddEmailMessageAsync(message).Forget();
|
||||
result = (await SendMailWithSendgrid(message)).ToString(); //?? HttpStatusCode.BadRequest.ToString();
|
||||
//result = (await SendMailWithSendgrid(message)).ToString(); //?? HttpStatusCode.BadRequest.ToString();
|
||||
result = (await SendMailWithSmtp(message)).ToString(); //?? HttpStatusCode.BadRequest.ToString();
|
||||
break;
|
||||
case (int)MessageTypesEnum.sms:
|
||||
//await SendSmsWithTwilio(message.Message);
|
||||
|
|
@ -159,6 +166,197 @@ namespace TIAM.Services.Server
|
|||
|
||||
}
|
||||
|
||||
|
||||
//public async Task<HttpStatusCode> SendMailWithSmtp(EmailMessage message)
|
||||
//{
|
||||
// Console.WriteLine($"Sender: {message.SenderId}");
|
||||
// Console.WriteLine($"Message: {message.Text}");
|
||||
|
||||
// if (message.Recipients == null || !message.Recipients.Any())
|
||||
// {
|
||||
// return HttpStatusCode.BadRequest;
|
||||
// }
|
||||
|
||||
// using (var smtpClient = new SmtpClient(smtpHost, smtpPort))
|
||||
// {
|
||||
// smtpClient.Credentials = new NetworkCredential(smtpUser, smtpPass);
|
||||
// smtpClient.EnableSsl = true;
|
||||
|
||||
// var fromAddress = new MailAddress(smtpUser, "Your Mail Service");
|
||||
|
||||
// List<Task> sendTasks = new List<Task>();
|
||||
|
||||
// foreach (var recipient in message.Recipients)
|
||||
// {
|
||||
// var toAddress = new MailAddress(recipient.EmailAddress);
|
||||
// var mailMessage = new MailMessage(fromAddress, toAddress)
|
||||
// {
|
||||
// Subject = message.Subject,
|
||||
// Body = message.Text,
|
||||
// IsBodyHtml = true
|
||||
// };
|
||||
|
||||
// //sendTasks.Add(Task.Run(() => smtpClient.SendMailAsync(mailMessage)));
|
||||
// sendTasks.Add(smtpClient.SendMailAsync(mailMessage));
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// await Task.WhenAll(sendTasks);
|
||||
// Console.WriteLine("All emails sent successfully");
|
||||
// return HttpStatusCode.OK;
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine($"Failed to send emails: {ex.Message}");
|
||||
// return HttpStatusCode.InternalServerError;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//public async Task<HttpStatusCode> SendMailWithSmtp(EmailMessage message)
|
||||
//{
|
||||
// Console.WriteLine($"Sender: {message.SenderId}");
|
||||
// Console.WriteLine($"Message: {message.Text}");
|
||||
|
||||
// if (message.Recipients == null || !message.Recipients.Any())
|
||||
// {
|
||||
// return HttpStatusCode.BadRequest;
|
||||
// }
|
||||
|
||||
// List<Task> sendTasks = new List<Task>();
|
||||
|
||||
// foreach (var recipient in message.Recipients)
|
||||
// {
|
||||
// var smtpClient = new SmtpClient(smtpHost, smtpPort)
|
||||
// {
|
||||
// Credentials = new NetworkCredential(smtpUser, smtpPass),
|
||||
// EnableSsl = true,
|
||||
// TargetName = $"SMTPS/{smtpHost}"
|
||||
// };
|
||||
|
||||
// var fromAddress = new MailAddress(smtpUser, "Your Mail Service");
|
||||
// var toAddress = new MailAddress(recipient.EmailAddress);
|
||||
// var mailMessage = new MailMessage(fromAddress, toAddress)
|
||||
// {
|
||||
// Subject = message.Subject,
|
||||
// Body = message.Text,
|
||||
// IsBodyHtml = true
|
||||
// };
|
||||
|
||||
// sendTasks.Add(Task.Run(async () =>
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// await smtpClient.SendMailAsync(mailMessage);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine($"Failed to send email to {recipient.EmailAddress}: {ex.Message}");
|
||||
// throw; // Ensure exceptions bubble up
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// smtpClient.Dispose();
|
||||
// }
|
||||
// }));
|
||||
// }
|
||||
|
||||
// var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30)); // Prevent indefinite waiting
|
||||
// var allTasks = Task.WhenAll(sendTasks);
|
||||
// var completedTask = await Task.WhenAny(allTasks, timeoutTask);
|
||||
|
||||
// if (completedTask == timeoutTask)
|
||||
// {
|
||||
// Console.WriteLine("Email sending timed out.");
|
||||
// return HttpStatusCode.RequestTimeout;
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// await allTasks; // Rethrow if there were failures
|
||||
// Console.WriteLine("All emails sent successfully");
|
||||
// return HttpStatusCode.OK;
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// Console.WriteLine("Some emails failed to send");
|
||||
// return HttpStatusCode.InternalServerError;
|
||||
// }
|
||||
//}
|
||||
|
||||
public async Task<HttpStatusCode> SendMailWithSmtp(EmailMessage message)
|
||||
{
|
||||
Console.WriteLine($"Sender: {message.SenderId}");
|
||||
Console.WriteLine($"Message: {message.Text}");
|
||||
|
||||
if (message.Recipients == null || !message.Recipients.Any())
|
||||
{
|
||||
return HttpStatusCode.BadRequest;
|
||||
}
|
||||
|
||||
List<Task> sendTasks = new List<Task>();
|
||||
|
||||
foreach (var recipient in message.Recipients)
|
||||
{
|
||||
sendTasks.Add(Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var smtpClient = new SmtpClient(smtpHost, smtpPort))
|
||||
{
|
||||
smtpClient.Credentials = new NetworkCredential(smtpUser, smtpPass);
|
||||
smtpClient.EnableSsl = true; // Try false for port 587
|
||||
smtpClient.TargetName = $"SMTPS/{smtpHost}";
|
||||
|
||||
var fromAddress = new MailAddress(smtpUser, "Your Mail Service");
|
||||
var toAddress = new MailAddress(recipient.EmailAddress);
|
||||
var mailMessage = new MailMessage(fromAddress, toAddress)
|
||||
{
|
||||
Subject = message.Subject,
|
||||
Body = message.Text,
|
||||
IsBodyHtml = true
|
||||
};
|
||||
|
||||
await smtpClient.SendMailAsync(mailMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Failed to send email to {recipient.EmailAddress}: {ex.Message}");
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30)); // Prevent indefinite waiting
|
||||
var allTasks = Task.WhenAll(sendTasks);
|
||||
var completedTask = await Task.WhenAny(allTasks, timeoutTask);
|
||||
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
Console.WriteLine("Email sending timed out.");
|
||||
return HttpStatusCode.RequestTimeout;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await allTasks; // Rethrow if there were failures
|
||||
Console.WriteLine("All emails sent successfully");
|
||||
return HttpStatusCode.OK;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine("Some emails failed to send");
|
||||
return HttpStatusCode.InternalServerError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string GenerateWelcomeEmail(string userName, string activationCode)
|
||||
{
|
||||
string template = EmailTemplateHelper.GetTemplate(TiamConstClient.WelcomeEmailTemplateName);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>D:\REPOS\TOURIAM_PUBLISH</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Blazor" Version="24.2.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.10" />
|
||||
<PackageReference Include="SendGrid" Version="9.29.3" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace TIAM.Services.Server
|
|||
};
|
||||
}
|
||||
|
||||
public double GetCommission(Guid productId, double Price, TransferDestination to)
|
||||
public double GetCommission(Guid productId, double price, TransferDestination to)
|
||||
{
|
||||
//check if Destination has a custom commissionRate by productId
|
||||
double commissionRate = 0;
|
||||
|
|
@ -92,7 +92,7 @@ namespace TIAM.Services.Server
|
|||
|
||||
}
|
||||
}
|
||||
commission = GetCommission(Price, commissionRate);
|
||||
commission = GetCommission(price, commissionRate);
|
||||
return commission;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="24.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TIAM.Core\TIAM.Core.csproj" />
|
||||
<ProjectReference Include="..\TIAM.Entities\TIAM.Entities.csproj" />
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.8" />
|
||||
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" VersionOverride="7.0.1" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" VersionOverride="7.0.1" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<IsFirstTimeProjectOpen>False</IsFirstTimeProjectOpen>
|
||||
<ActiveDebugFramework>net8.0-windows10.0.19041.0</ActiveDebugFramework>
|
||||
<ActiveDebugProfile>Windows Machine</ActiveDebugProfile>
|
||||
<ActiveDebugFramework>net8.0-maccatalyst</ActiveDebugFramework>
|
||||
<ActiveDebugProfile>Mac Catalyst</ActiveDebugProfile>
|
||||
<SelectedPlatformGroup>PhysicalDevice</SelectedPlatformGroup>
|
||||
<DefaultDevice>pixel_5_-_api_31</DefaultDevice>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -384,6 +384,15 @@ namespace TIAM.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Who we are.
|
||||
/// </summary>
|
||||
public static string Index_WhoWeAre {
|
||||
get {
|
||||
return ResourceManager.GetString("Index.WhoWeAre", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Login.
|
||||
/// </summary>
|
||||
|
|
@ -456,6 +465,24 @@ namespace TIAM.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Book now!.
|
||||
/// </summary>
|
||||
public static string NavMenu_BookNow {
|
||||
get {
|
||||
return ResourceManager.GetString("NavMenu.BookNow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Contact.
|
||||
/// </summary>
|
||||
public static string NavMenu_Contact {
|
||||
get {
|
||||
return ResourceManager.GetString("NavMenu.Contact", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Events.
|
||||
/// </summary>
|
||||
|
|
@ -465,6 +492,15 @@ namespace TIAM.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Explore the region.
|
||||
/// </summary>
|
||||
public static string NavMenu_ExploreTheRegion {
|
||||
get {
|
||||
return ResourceManager.GetString("NavMenu.ExploreTheRegion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to FormulaOne.
|
||||
/// </summary>
|
||||
|
|
@ -483,6 +519,15 @@ namespace TIAM.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to How it works.
|
||||
/// </summary>
|
||||
public static string NavMenu_HowItWorks {
|
||||
get {
|
||||
return ResourceManager.GetString("NavMenu.HowItWorks", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Login.
|
||||
/// </summary>
|
||||
|
|
@ -510,6 +555,15 @@ namespace TIAM.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Signature ride packages.
|
||||
/// </summary>
|
||||
public static string NavMenu_SignatureRidePackages {
|
||||
get {
|
||||
return ResourceManager.GetString("NavMenu.SignatureRidePackages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sign out.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -249,15 +249,27 @@
|
|||
<data name="NavMenu.Admin" xml:space="preserve">
|
||||
<value>Adminisztráció</value>
|
||||
</data>
|
||||
<data name="NavMenu.BookNow" xml:space="preserve">
|
||||
<value>Foglalj most!</value>
|
||||
</data>
|
||||
<data name="NavMenu.Contact" xml:space="preserve">
|
||||
<value>Kapcsolat</value>
|
||||
</data>
|
||||
<data name="NavMenu.Events" xml:space="preserve">
|
||||
<value>Események</value>
|
||||
</data>
|
||||
<data name="NavMenu.ExploreTheRegion" xml:space="preserve">
|
||||
<value>Fedezd fel a térséget</value>
|
||||
</data>
|
||||
<data name="NavMenu.FormulaOne" xml:space="preserve">
|
||||
<value>Forma1</value>
|
||||
</data>
|
||||
<data name="NavMenu.Home" xml:space="preserve">
|
||||
<value>Főoldal</value>
|
||||
</data>
|
||||
<data name="NavMenu.HowItWorks" xml:space="preserve">
|
||||
<value>Miben más a TourIam</value>
|
||||
</data>
|
||||
<data name="NavMenu.Login" xml:space="preserve">
|
||||
<value>Belépés</value>
|
||||
</data>
|
||||
|
|
@ -267,6 +279,9 @@
|
|||
<data name="NavMenu.Settings" xml:space="preserve">
|
||||
<value>Beállítások</value>
|
||||
</data>
|
||||
<data name="NavMenu.SignatureRidePackages" xml:space="preserve">
|
||||
<value>Túrák</value>
|
||||
</data>
|
||||
<data name="NavMenu.SignOut" xml:space="preserve">
|
||||
<value>Kijelentkezés</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -225,6 +225,9 @@
|
|||
<data name="Index.Transfer.Desc" xml:space="preserve">
|
||||
<value>Do you need a lift? Book a transfer now!</value>
|
||||
</data>
|
||||
<data name="Index.WhoWeAre" xml:space="preserve">
|
||||
<value>Who we are</value>
|
||||
</data>
|
||||
<data name="Login" xml:space="preserve">
|
||||
<value>Login</value>
|
||||
</data>
|
||||
|
|
@ -249,15 +252,27 @@
|
|||
<data name="NavMenu.Admin" xml:space="preserve">
|
||||
<value>Admin</value>
|
||||
</data>
|
||||
<data name="NavMenu.BookNow" xml:space="preserve">
|
||||
<value>Book now!</value>
|
||||
</data>
|
||||
<data name="NavMenu.Contact" xml:space="preserve">
|
||||
<value>Contact</value>
|
||||
</data>
|
||||
<data name="NavMenu.Events" xml:space="preserve">
|
||||
<value>Events</value>
|
||||
</data>
|
||||
<data name="NavMenu.ExploreTheRegion" xml:space="preserve">
|
||||
<value>Explore the region</value>
|
||||
</data>
|
||||
<data name="NavMenu.FormulaOne" xml:space="preserve">
|
||||
<value>FormulaOne</value>
|
||||
</data>
|
||||
<data name="NavMenu.Home" xml:space="preserve">
|
||||
<value>Home</value>
|
||||
</data>
|
||||
<data name="NavMenu.HowItWorks" xml:space="preserve">
|
||||
<value>How it works</value>
|
||||
</data>
|
||||
<data name="NavMenu.Login" xml:space="preserve">
|
||||
<value>Login</value>
|
||||
</data>
|
||||
|
|
@ -267,6 +282,9 @@
|
|||
<data name="NavMenu.Settings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="NavMenu.SignatureRidePackages" xml:space="preserve">
|
||||
<value>Signature ride packages</value>
|
||||
</data>
|
||||
<data name="NavMenu.SignOut" xml:space="preserve">
|
||||
<value>Sign out</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@
|
|||
|
||||
At Tour I Am, we understand the importance of a seamless and comfortable journey for our valued customers. Whether you're arriving in Budapest for business or leisure, our dedicated team ensures that your transfer experience is hassle-free and enjoyable.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<p class="mb-4 pe-xl-12 ">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
@page "/blogpost/{PostId}"
|
||||
@using TIAMSharedUI.Pages.Components
|
||||
@using TIAMSharedUI.Shared
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@inject HttpClient Http
|
||||
@inject BlogService BlogService
|
||||
|
||||
<HeroSlider SliderItems="@sliders" PBottom="50px" Height="30vh"></HeroSlider>
|
||||
|
||||
@if (Content == null)
|
||||
{
|
||||
<p>Loading post...</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="container">
|
||||
|
||||
<div class="card p-3" @onclick:stopPropagation>
|
||||
@((MarkupString)Content)
|
||||
</div>
|
||||
|
||||
@if (Tags?.Count > 0)
|
||||
{
|
||||
<p class="mt-3 text-muted small">
|
||||
Tags: @string.Join(", ", Tags)
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<CallToActionComponent></CallToActionComponent>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string PostId { get; set; }
|
||||
|
||||
private string? Content;
|
||||
private string? Title;
|
||||
private string? CoverImage;
|
||||
private List<string>? Tags;
|
||||
|
||||
|
||||
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var post = await BlogService.GetPostByIdAsync(PostId);
|
||||
if (post != null)
|
||||
{
|
||||
Title = post.Title;
|
||||
CoverImage = post.CoverImage;
|
||||
Tags = post.Tags;
|
||||
|
||||
// ✅ Extract fileId from DriveLink:
|
||||
var fileId = ExtractGoogleDriveFileId(post.DriveLink);
|
||||
if (!string.IsNullOrEmpty(fileId))
|
||||
{
|
||||
// string apiKey = "AIzaSyBLKx4XFpgX97sULTbtpyKA2Ca_ANrjxxs"; // your existing key
|
||||
// // string downloadUrl = $"https://www.googleapis.com/drive/v3/files/{fileId}?alt=media&key={apiKey}";
|
||||
// string downloadUrl = $"https://drive.google.com/uc?export=download&id={fileId}";
|
||||
// Content = await Http.GetStringAsync(downloadUrl);
|
||||
|
||||
Content = null; // Optional: clear previous content while loading new
|
||||
|
||||
try
|
||||
{
|
||||
Content = await Http.GetStringAsync($"/api/blog/postcontent/{PostId}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Content = "<p class='text-danger'>Failed to load blog post.</p>";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Content = "<p class='text-danger'>Invalid Google Drive link in post metadata.</p>";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Content = "<p class='text-danger'>Failed to load blog post. " + e.ToString()+ "</p>";
|
||||
}
|
||||
}
|
||||
|
||||
private string? ExtractGoogleDriveFileId(string driveLink)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Works with typical Google Drive URLs
|
||||
var match = System.Text.RegularExpressions.Regex.Match(driveLink, @"\/d\/([^\/]+)");
|
||||
return match.Success ? match.Groups[1].Value : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<HeroSliderItem> sliders = new()
|
||||
{
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Explore Our Programs",
|
||||
ButtonUrl= "/signature-ride-packages"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Book now",
|
||||
ButtonUrl= "/transfer"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "",
|
||||
ButtonUrl= ""
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
@using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
@using DevExpress.Blazor
|
||||
@using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
@using TIAMWebApp.Shared.Application.Models;
|
||||
@using TIAMWebApp.Shared.Application.Interfaces;
|
||||
@inject ISessionServiceClient sessionService;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<div class="container text-center py-4 py-md-6 rounded-3">
|
||||
<div class="lc-block card border-0 text-center rounded p-4 p-lg-6" style="background:url(https://cdn.livecanvas.com/media/backgrounds/fffuelco/ffflux.svg) center / cover no-repeat;">
|
||||
<div class="container-fluid text-center pt-4 py-md-6">
|
||||
<div class="lc-block card border-0 text-center py-5" style="background: #4c327b; background-position: center; background-size: cover;">
|
||||
<div class="row card-body mb-3 mb-lg-4">
|
||||
<div class="col-xl-11 col-xxl-9 mx-auto">
|
||||
<div class="lc-block mb-4">
|
||||
<div editable="rich">
|
||||
<p class="text-white">JOIN OUR COMMUNITY</p>
|
||||
<p class="text-white">READY TO GO?</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lc-block">
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lc-block"><a class="btn btn-primary btn-lg" href="#" role="button">Get Started</a></div>
|
||||
<div class="lc-block"><a class="btn btn-primary btn-lg" href="#" role="button">Book now!</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
@using System.Text
|
||||
@using AyCode.Core.Helpers
|
||||
@using TIAM.Entities.Transfers
|
||||
@using TIAM.Services
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@inject AdminSignalRClient _adminSignalRClient;
|
||||
|
||||
<p>@DriverName</p>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid TransferId { get; set; }
|
||||
private string DriverName = "";
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
_adminSignalRClient.GetByIdAsync<List<TransferToDriver>>(SignalRTags.GetTransferDriversByTransferId, x =>
|
||||
{
|
||||
//await Task.Delay(1);
|
||||
var keyItemTransferToDriver = x.ResponseData;
|
||||
|
||||
if (keyItemTransferToDriver != null && keyItemTransferToDriver.Count > 0)
|
||||
{
|
||||
foreach (var driver in keyItemTransferToDriver)
|
||||
{
|
||||
if (driver != null && driver.UserProductMapping != null)
|
||||
{
|
||||
if (driver.UserProductMapping.User != null)
|
||||
{
|
||||
|
||||
if (driver.UserProductMapping.User.Profile != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(driver.UserProductMapping.User.Profile.Name))
|
||||
{
|
||||
DriverName = driver.UserProductMapping.User.Profile.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
DriverName = driver.LicencePlate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DriverName = "No driver assigned yet";
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, TransferId).Forget();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
@using TIAMWebApp.Shared.Application.Models;
|
||||
@using DevExpress.Blazor
|
||||
@using TIAMWebApp.Shared.Application.Models;
|
||||
@using TIAMWebApp.Shared.Application.Interfaces;
|
||||
@inject ISessionServiceClient sessionService;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@
|
|||
</div>
|
||||
|
||||
<DxPopup CssClass="popup-demo-events"
|
||||
@bind-Visible="@_popupVisible"
|
||||
ShowFooter="true"
|
||||
CloseOnEscape="true"
|
||||
CloseOnOutsideClick="false"
|
||||
ShowCloseButton="false"
|
||||
HeaderText="MessageBox"
|
||||
Closing="EmailPopupClosing"
|
||||
Closed="EmailPopupClosed"
|
||||
SizeMode="SizeMode.Large">
|
||||
@bind-Visible="@_popupVisible"
|
||||
ShowFooter="true"
|
||||
CloseOnEscape="true"
|
||||
CloseOnOutsideClick="false"
|
||||
ShowCloseButton="false"
|
||||
HeaderText="MessageBox"
|
||||
Closing="EmailPopupClosing"
|
||||
Closed="EmailPopupClosed"
|
||||
SizeMode="SizeMode.Large">
|
||||
<BodyContentTemplate>
|
||||
@{
|
||||
if(showResultMessage)
|
||||
|
|
@ -56,14 +56,14 @@
|
|||
else
|
||||
{
|
||||
<DynamicEditForm Data=@_messageWizardModel
|
||||
OnSubmit="SubmitForm"
|
||||
TitleString="New message"
|
||||
ButtonTextString="Send message"
|
||||
isEditing="true"
|
||||
IgnoreReflection=@IgnoreList></DynamicEditForm>
|
||||
OnSubmit="SubmitForm"
|
||||
TitleString="New message"
|
||||
ButtonTextString="Send message"
|
||||
isEditing="true"
|
||||
IgnoreReflection=@IgnoreList></DynamicEditForm>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</BodyContentTemplate>
|
||||
<FooterContentTemplate Context="Context">
|
||||
@{
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</FooterContentTemplate>
|
||||
</DxPopup>
|
||||
|
||||
|
|
@ -92,8 +92,8 @@
|
|||
{
|
||||
<div class="text-center m-5">
|
||||
<DxWaitIndicator Visible="true"
|
||||
CssClass="m-auto"
|
||||
AnimationType="WaitIndicatorAnimationType.Spin" />
|
||||
CssClass="m-auto"
|
||||
AnimationType="WaitIndicatorAnimationType.Spin" />
|
||||
</div>
|
||||
|
||||
}
|
||||
|
|
@ -152,11 +152,11 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
<p class="text-muted">Status on: <span class="text-body">@DateTime.Now.ToString("hh:mm tt"), @DateTime.Today.ToString("MMMM dd, yyyy")</span></p>
|
||||
<h5 class="text-muted">@TransferStatusModel.GetStatusModel(_transfer.TransferStatusType);</h5>
|
||||
|
||||
<h5 class="text-muted">@TransferStatusModel.GetStatusModel(_transfer.TransferStatusType).StatusName;</h5>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
|
|
@ -175,7 +175,7 @@ else
|
|||
<h5 class="fw-normal mb-0"><DxButton RenderStyle="ButtonRenderStyle.Warning" Click="CancelTransfer">Cancel</DxButton></h5>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<div class="vr"></div>
|
||||
@{
|
||||
if(_transfer.Price != null || _transfer.Price != 0)
|
||||
|
|
@ -184,7 +184,7 @@ else
|
|||
<div class="vr"></div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@*<h5 class="fw-normal mb-0"><a class="btn btn-secondary" @onclick="SetEditMode">Modify</a></h5>*@
|
||||
<h5 class="fw-normal mb-0"><DxButton RenderStyle="ButtonRenderStyle.Secondary" Click="SetEditMode">Modify</DxButton></h5>
|
||||
</div>
|
||||
|
|
@ -251,7 +251,7 @@ else
|
|||
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Appointment">
|
||||
<DxDateEdit TimeSectionVisible="true" @bind-Date="_transfer.Appointment" />
|
||||
</DxFormLayoutItem>
|
||||
|
||||
|
||||
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Passenger Count">
|
||||
<DxSpinEdit @bind-Value="_transfer.PassengerCount" />
|
||||
</DxFormLayoutItem>
|
||||
|
|
@ -267,7 +267,7 @@ else
|
|||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="d-flex flex-row mb-4 pb-2">
|
||||
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Comment">
|
||||
<DxMemo @bind-Text="_transfer.Comment" />
|
||||
|
|
@ -276,6 +276,7 @@ else
|
|||
</div>
|
||||
<div class="card-footer p-4">
|
||||
<div class="d-flex justify-content-between">
|
||||
<DxButton RenderStyle="ButtonRenderStyle.Warning" Click="@((e) => CancelTransferEventHandler(e, true))">Discard changes</DxButton>
|
||||
<DxButton Click="@((e) => UpdateTransferEventHandler(e, true))">Save Changes</DxButton>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -292,7 +293,7 @@ else
|
|||
<div style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<DxButton Click="() => SendMail(_transfer)" Text="Send a message" RenderStyle="ButtonRenderStyle.Primary" />
|
||||
</div>
|
||||
<MessageDetailGridComponent ContextId="transferId" IsSenderEmailVisible="false" IsMessageTextVisible="false"></MessageDetailGridComponent>
|
||||
<MessageDetailGridComponent ContextId="_transfer.Id" GetAllMessageTag="SignalRTags.GetMessagesByContextId" IsSenderEmailVisible="false" IsMessageTextVisible="false"></MessageDetailGridComponent>
|
||||
</DxTabPage>
|
||||
</DxTabs>
|
||||
</div>
|
||||
|
|
@ -523,8 +524,14 @@ else
|
|||
private async Task UpdateTransferEventHandler(MouseEventArgs e, bool shouldRedirect = false)
|
||||
{
|
||||
var result = await UpdateTransfer(shouldRedirect);
|
||||
_editMode = false;
|
||||
if (result != null && shouldRedirect)
|
||||
navManager.NavigateTo("/mytransfers"); // Redirect to a list or another page after successful update
|
||||
navManager.NavigateTo($"/mytransfers/{_transfer.Id}"); // Redirect to a list or another page after successful update
|
||||
}
|
||||
|
||||
private async Task CancelTransferEventHandler(MouseEventArgs e, bool shouldRedirect = false)
|
||||
{
|
||||
_editMode = false;
|
||||
}
|
||||
|
||||
private async Task<Transfer?> UpdateTransfer(bool shouldRedirect = false)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<div class="item" style="background-image: url(@item.ImageUrl);">
|
||||
|
||||
<div class="item-desc" style="height: 100%; background-color: rgba(0,0,0,0.3);">
|
||||
<!--h3>item.Name</h3-->
|
||||
|
||||
|
||||
<h3 class="card-title" style="margin-top: 80px;">@item.Name</h3>
|
||||
<p>@item.DateAndTime</p>
|
||||
|
|
@ -37,14 +37,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="login">
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -102,4 +95,4 @@
|
|||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -35,15 +35,15 @@
|
|||
@_localizer["LoginTitleText"]
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<DxMaskedInput @bind-Value="@emailAddress"
|
||||
Id="Email"
|
||||
CssClass="form-control"
|
||||
Mask="@EmailMask"
|
||||
MaskMode="MaskMode.RegEx">
|
||||
<DxRegExMaskProperties MaskAutoCompleteMode="@((MaskAutoCompleteMode)AutoCompleteMode)"
|
||||
Placeholder="Placeholder"
|
||||
PlaceholdersVisible="PlaceholderVisible" />
|
||||
</DxMaskedInput>
|
||||
<DxMaskedInput @bind-Value="@emailAddress"
|
||||
Id="Email"
|
||||
CssClass="form-control"
|
||||
Mask="@EmailMask"
|
||||
MaskMode="MaskMode.RegEx">
|
||||
<DxRegExMaskProperties MaskAutoCompleteMode="@((MaskAutoCompleteMode)AutoCompleteMode)"
|
||||
Placeholder="Placeholder"
|
||||
PlaceholdersVisible="PlaceholderVisible" />
|
||||
</DxMaskedInput>
|
||||
</div>
|
||||
<DxButton CssClass="btn btn-primary mt-3" Click="() => SendMail(emailAddress)">Send</DxButton>
|
||||
<div class="text-center fs-6">
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<p>
|
||||
@msg;
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
</Animation>
|
||||
|
|
@ -88,6 +88,6 @@
|
|||
private void SendMail(string email)
|
||||
{
|
||||
var sendResult = UserDataService.SendForgottenPasswordMail(emailAddress).Forget;
|
||||
|
||||
msg = "We have sent you an email, with instructions on how to renew your password. ";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
@page "/"
|
||||
@using AyCode.Interfaces.StorageHandlers;
|
||||
@using BlazorAnimation
|
||||
@using TIAMSharedUI.Shared.Components
|
||||
@using TIAMSharedUI.Shared.Components.BaseComponents
|
||||
@using TIAMWebApp.Shared.Application.Interfaces
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
@using AyCode.Services.Loggers
|
||||
@using TIAMSharedUI.Pages.Components;
|
||||
|
|
@ -24,8 +26,8 @@
|
|||
|
||||
<AuthComponent />
|
||||
|
||||
<HeroSlider SliderItems="@sliders" PBottom="50px" Height="30vh"></HeroSlider>
|
||||
@* <div class="container-fluid" style="position: relative; z-index: 2;">
|
||||
<HeroSlider SliderItems="@sliders" PBottom="50px" Height="70vh"></HeroSlider>
|
||||
@* <div class="container-fluid" style="position: relative; z-index: 2;">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card bg-white p-3">
|
||||
|
|
@ -42,9 +44,7 @@
|
|||
</div> *@
|
||||
|
||||
|
||||
<div class="container-fluid" style="align-content: center;">
|
||||
|
||||
|
||||
@* <div class="container-fluid" style="align-content: center;">
|
||||
|
||||
<div class="text-center">
|
||||
|
||||
|
|
@ -52,49 +52,49 @@
|
|||
<h2>@localizer.GetString("Index.Subtitle")</h2>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
</div> *@
|
||||
|
||||
<NavLink class="nav-link col-md-6 col-lg-4 col-12" href="transfer">
|
||||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<div class="card m-3 my-card text-white">
|
||||
<img class="card-img" src="_content/TIAMSharedUI/images/m_transfer.jpg" alt="Card image">
|
||||
<div class="card-img-overlay">
|
||||
|
||||
<h3 class="card-title">@localizer.GetString("Index.Transfer")</h3>
|
||||
|
||||
<p class="card-text">@localizer.GetString("Index.Transfer.Desc")</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Animation>
|
||||
</NavLink>
|
||||
<NavLink class="nav-link col-md-6 col-lg-4 col-12" href="tours">
|
||||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<div class="card m-3 my-card text-white">
|
||||
<img class="card-img" src="_content/TIAMSharedUI/images/m_tour.jpg" alt="Card image">
|
||||
<div class="card-img-overlay">
|
||||
<h3 class="card-title">@localizer.GetString("Index.Tours")</h3>
|
||||
<p class="card-text">@localizer.GetString("Index.Tours.Desc")</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Animation>
|
||||
</NavLink>
|
||||
<NavLink class="nav-link col-md-6 col-lg-4 col-12" href="clubcards">
|
||||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<div class="card m-3 my-card text-white">
|
||||
<img class="card-img" src="_content/TIAMSharedUI/images/m_restaurant.jpg" alt="Card image">
|
||||
<div class="card-img-overlay">
|
||||
<h3 class="card-title">@localizer.GetString("Index.Clubcards")</h3>
|
||||
<p class="card-text">@localizer.GetString("Index.Clubcards.Desc")</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Animation>
|
||||
</NavLink>
|
||||
<section class="py-5 bg-light">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<!-- Text Content -->
|
||||
<div class="col-md-6">
|
||||
<h2>@localizer.GetString("Index.WhoWeAre")</h2>
|
||||
<p>We’re not here to take over your trip. We’re here to help shape it — with smooth rides, flexible options, and curated experiences you can actually enjoy.</p>
|
||||
<p>Think of us as your private ride — whether you’re heading to the airport, a spa town, a winery, or somewhere off the map.</p>
|
||||
<p>You can follow one of our signature routes, or create your own. We adapt. You decide. We take care of the road.</p>
|
||||
<p>Our role changes with every guest. Sometimes we’re your calm in the chaos. Sometimes we’re your quiet local expert. Sometimes we’re just there — when you need someone who knows the way.</p>
|
||||
</div>
|
||||
<!-- Image Placeholder -->
|
||||
<div class="col-md-6 text-center">
|
||||
<img src="https://images.unsplash.com/photo-1563461660947-507ef49e9c47?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Who we are" class="img-fluid rounded shadow">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<section class="py-5 bg-gradient">
|
||||
<ToursComponent />
|
||||
</section>
|
||||
<section class="py-5">
|
||||
<BlogComponent />
|
||||
</section>
|
||||
|
||||
<CallToActionComponent></CallToActionComponent>
|
||||
|
||||
<script>
|
||||
$(".custom-carousel").owlCarousel({
|
||||
autoWidth: true,
|
||||
loop: true
|
||||
});
|
||||
$(document).ready(function () {
|
||||
$(".custom-carousel .item").click(function () {
|
||||
$(".custom-carousel .item").not($(this)).removeClass("active");
|
||||
$(this).toggleClass("active");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@code {
|
||||
|
||||
|
|
@ -102,18 +102,27 @@
|
|||
{
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Welcome to TIAM",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Explore Our Programs",
|
||||
ButtonUrl= "/signature-ride-packages"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Welcome to TIAM",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Book now",
|
||||
ButtonUrl= "/transfer"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Welcome to TIAM",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "",
|
||||
ButtonUrl= ""
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -122,8 +131,8 @@
|
|||
public List<string> TransferIgnorList = new List<string>
|
||||
{
|
||||
"Id",
|
||||
"UserId",
|
||||
"ProductId",
|
||||
"UserId",
|
||||
"ProductId",
|
||||
"PaymentId",
|
||||
"FirstName",
|
||||
"LastName",
|
||||
|
|
@ -134,24 +143,37 @@
|
|||
"Revenue"
|
||||
};
|
||||
|
||||
/*protected override void OnAfterRender(bool isFirst)
|
||||
{
|
||||
message = " Target destination is " + slider.SliderElementId.ToString();
|
||||
}*/
|
||||
/*protected override void OnAfterRender(bool isFirst)
|
||||
{
|
||||
message = " Target destination is " + slider.SliderElementId.ToString();
|
||||
}*/
|
||||
|
||||
public async Task SubmitForm(object Result)
|
||||
{
|
||||
TransferWizardModel transferWizardModel = Result as TransferWizardModel;
|
||||
if(sessionService.IsAuthenticated)
|
||||
{
|
||||
transferWizardModel.UserId = sessionService.User.UserModelDto.Id;
|
||||
transferWizardModel.ProductId = sessionService.User.UserModelDto.Products.FirstOrDefault().Id;
|
||||
}
|
||||
transferWizardModel.Price = null;
|
||||
var transfer = await WizardProcessor.ProcessWizardAsync<TransferWizardModel>(transferWizardModel.GetType(), transferWizardModel);
|
||||
BrowserConsoleLogWriter.Info($"Submitted nested form: {Result.GetType().FullName}");
|
||||
navManager.NavigateTo("/transfer2/" + transfer.Id);
|
||||
TransferWizardModel transferWizardModel = Result as TransferWizardModel;
|
||||
if (sessionService.IsAuthenticated)
|
||||
{
|
||||
transferWizardModel.UserId = sessionService.User.UserModelDto.Id;
|
||||
transferWizardModel.ProductId = sessionService.User.UserModelDto.Products.FirstOrDefault().Id;
|
||||
}
|
||||
transferWizardModel.Price = null;
|
||||
var transfer = await WizardProcessor.ProcessWizardAsync<TransferWizardModel>(transferWizardModel.GetType(), transferWizardModel);
|
||||
BrowserConsoleLogWriter.Info($"Submitted nested form: {Result.GetType().FullName}");
|
||||
navManager.NavigateTo("/transfer2/" + transfer.Id);
|
||||
}
|
||||
|
||||
public List<Event> MockEvents = new List<Event>
|
||||
{
|
||||
new Event("HONEYBEAST", "A Honeybeast egyedisége abban rejlik, hogy a popzenét rengeteg különféle irányból közelítik meg - hol vidám, hol szomorú, hol pörgős, hogy lassú, koncertjükön az érzelmek széles skáláját élhetjük át együtt.", "2024.05.03", "Budapest Park", "https://tixa.hu/kepek/0027/320/27870-1_20231214141702.jpg"),
|
||||
new Event("VAD FRUTTIK", "A kék a tenger és az ég színe, a nyílt terekkel, valamint a képzelettel és tágassággal társul - végtelen kékség május 3-án a Budapest Parkban!", "2024.04.26", "Budapest Park", "https://tixa.hu/kepek/0027/768/27692-1_20231129185842.jpg"),
|
||||
new Event("DEBORAH DE LUCA", "DEBORAH DE LUCA 2024-ben Magyarországon csak a Budapest Park színpadán", "2024.08.19", "Budapest Park", "https://tixa.hu/kepek/0028/768/28535-1_20240118172423.jpg"),
|
||||
new Event("TOTAL DANCE CABRIO", "Ha nyár, akkor Total Dance Cabrio! Ülj be mellénk a cabrioba, és hagyd, hogy visszarepítsünk a 90-es és 2000-es évekbe! ", "2024.04.26", "Budapest Park", "https://tixa.hu/kepek/0027/768/27829-1_20231206193253.jpg"),
|
||||
new Event("HONEYBEAST", "A Honeybeast egyedisége abban rejlik, hogy a popzenét rengeteg különféle irányból közelítik meg - hol vidám, hol szomorú, hol pörgős, hogy lassú, koncertjükön az érzelmek széles skáláját élhetjük át együtt.", "2024.05.03", "Budapest Park", "https://tixa.hu/kepek/0027/320/27870-1_20231214141702.jpg"),
|
||||
new Event("VAD FRUTTIK", "A kék a tenger és az ég színe, a nyílt terekkel, valamint a képzelettel és tágassággal társul - végtelen kékség május 3-án a Budapest Parkban!", "2024.04.26", "Budapest Park", "https://tixa.hu/kepek/0027/768/27692-1_20231129185842.jpg"),
|
||||
new Event("DEBORAH DE LUCA", "DEBORAH DE LUCA 2024-ben Magyarországon csak a Budapest Park színpadán", "2024.08.19", "Budapest Park", "https://tixa.hu/kepek/0028/768/28535-1_20240118172423.jpg"),
|
||||
new Event("TOTAL DANCE CABRIO", "Ha nyár, akkor Total Dance Cabrio! Ülj be mellénk a cabrioba, és hagyd, hogy visszarepítsünk a 90-es és 2000-es évekbe! ", "2024.04.26", "Budapest Park", "https://tixa.hu/kepek/0027/768/27829-1_20231206193253.jpg"),
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@
|
|||
|
||||
<h3>Partner:</h3>
|
||||
<p>@SelectedHotel</p>
|
||||
|
||||
|
||||
<div class="row py-3">
|
||||
|
||||
|
||||
<DynamicEditForm Data="Data" isEditing="true" IgnoreReflection="TransferIgnorList" OnSubmit="SubmitForm"></DynamicEditForm>
|
||||
</div>
|
||||
|
||||
<div class="row py-3">
|
||||
|
||||
|
||||
<DxButton RenderStyle="ButtonRenderStyle.Primary" Click="@Reload" Visible="@isReloadVisible">Reload</DxButton>
|
||||
</div>
|
||||
|
||||
|
|
@ -91,9 +91,10 @@
|
|||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if(productId.IsNullOrEmpty())
|
||||
if(!productId.IsNullOrEmpty())
|
||||
{
|
||||
var result = await _adminSignalRClient.GetByIdAsync<Product>(SignalRTags.GetCompaniesById, productId);
|
||||
var result = await _adminSignalRClient.GetByIdAsync<Product>(SignalRTags.GetProductById, productId);
|
||||
_logger.Debug($"Current product: {result.Name}");
|
||||
if (result != null)
|
||||
{
|
||||
SelectedHotel = result;
|
||||
|
|
@ -103,7 +104,7 @@
|
|||
SelectedHotel = null;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug($"OnParameterSet, going forward");
|
||||
if (!referralId.IsNullOrEmpty())
|
||||
{
|
||||
//check if storage has some other referralId already TODO
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
@page "/backgroundtest"
|
||||
@inject IStringLocalizer<TIAMResources> localizer;
|
||||
@using TIAM.Resources
|
||||
@using TIAMSharedUI.Shared
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
|
||||
<div class="hero">
|
||||
|
||||
<div class="parallax-layer layer-6"></div>
|
||||
<div class="parallax-layer layer-5"></div>
|
||||
<div class="parallax-layer layer-4"></div>
|
||||
<div class="parallax-layer bike-1"></div>
|
||||
<div class="parallax-layer bike-2"></div>
|
||||
<div class="parallax-layer layer-3"></div>
|
||||
<div class="parallax-layer layer-2"></div>
|
||||
<div class="parallax-layer layer-1"></div>
|
||||
<div class="logo">
|
||||
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/logo.svg" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HeroSlider SliderItems="@sliders" PBottom="50px" Height="70vh"></HeroSlider>
|
||||
|
||||
<section class="py-5 bg-light">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<!-- Text Content -->
|
||||
<div class="col-md-6">
|
||||
<h2>@localizer.GetString("Index.WhoWeAre")</h2>
|
||||
<p>We’re not here to take over your trip. We’re here to help shape it — with smooth rides, flexible options, and curated experiences you can actually enjoy.</p>
|
||||
<p>Think of us as your private ride — whether you’re heading to the airport, a spa town, a winery, or somewhere off the map.</p>
|
||||
<p>You can follow one of our signature routes, or create your own. We adapt. You decide. We take care of the road.</p>
|
||||
<p>Our role changes with every guest. Sometimes we’re your calm in the chaos. Sometimes we’re your quiet local expert. Sometimes we’re just there — when you need someone who knows the way.</p>
|
||||
</div>
|
||||
<!-- Image Placeholder -->
|
||||
<div class="col-md-6 text-center">
|
||||
<img src="https://via.placeholder.com/500x350" alt="Who we are" class="img-fluid rounded shadow">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@code {
|
||||
public List<HeroSliderItem> sliders = new List<HeroSliderItem>
|
||||
{
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Explore Our Programs",
|
||||
ButtonUrl= "/signature-ride-packages"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Book now",
|
||||
ButtonUrl= "/transfer"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "",
|
||||
ButtonUrl= ""
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Lato", sans-serif;
|
||||
}
|
||||
|
||||
.hero {
|
||||
width: 100%;
|
||||
min-height: 450px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #d9edfd;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.layer-1 {
|
||||
-webkit-animation: parallax_fg linear 20s infinite both;
|
||||
animation: parallax_fg linear 20s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/1.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 136px;
|
||||
}
|
||||
|
||||
.layer-2 {
|
||||
-webkit-animation: parallax_fg linear 30s infinite both;
|
||||
animation: parallax_fg linear 30s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/2.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 145px;
|
||||
}
|
||||
|
||||
.layer-3 {
|
||||
-webkit-animation: parallax_fg linear 55s infinite both;
|
||||
animation: parallax_fg linear 55s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/3.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 158px;
|
||||
}
|
||||
|
||||
.layer-4 {
|
||||
-webkit-animation: parallax_fg linear 75s infinite both;
|
||||
animation: parallax_fg linear 75s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/4.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 468px;
|
||||
}
|
||||
|
||||
.layer-5 {
|
||||
-webkit-animation: parallax_fg linear 95s infinite both;
|
||||
animation: parallax_fg linear 95s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/5.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 311px;
|
||||
}
|
||||
|
||||
.layer-6 {
|
||||
-webkit-animation: parallax_fg linear 120s infinite both;
|
||||
animation: parallax_fg linear 120s infinite both;
|
||||
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/24650/6.png) 0 100% repeat-x;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 222px;
|
||||
}
|
||||
|
||||
.bike-1,
|
||||
.bike-2 {
|
||||
background: url(images/car.png) 0 100% no-repeat;
|
||||
z-index: 1;
|
||||
position: fixed;
|
||||
bottom: 100px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: auto 75px;
|
||||
}
|
||||
|
||||
.bike-1 {
|
||||
-webkit-animation: parallax_bike linear 10s infinite both;
|
||||
animation: parallax_bike linear 10s infinite both;
|
||||
}
|
||||
|
||||
.bike-2 {
|
||||
-webkit-animation: parallax_bike linear 15s infinite both;
|
||||
animation: parallax_bike linear 15s infinite both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes parallax_fg {
|
||||
0% {
|
||||
background-position: 2765px 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 550px 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes parallax_fg {
|
||||
0% {
|
||||
background-position: 2765px 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 550px 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes parallax_bike {
|
||||
0% {
|
||||
background-position: -300px 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 2000px 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes parallax_bike {
|
||||
0% {
|
||||
background-position: -300px 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 2000px 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 70px auto;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.logo img {
|
||||
max-width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
@page "/tours"
|
||||
@using TIAMSharedUI.Shared
|
||||
|
||||
<HeroSlider></HeroSlider>
|
||||
|
||||
<div class="container">
|
||||
<section class="game-section" style="max-width: 100%; overflow-x:hidden">
|
||||
<div class="text-center">
|
||||
|
||||
<h1>Tours</h1>
|
||||
<h2>Please select!</h2>
|
||||
</div>
|
||||
<div class="owl-carousel custom-carousel owl-theme">
|
||||
<a href="login">
|
||||
<div class="item active" style="background-image: url(_content/TIAMSharedUI/images/slider1.jpg);">
|
||||
|
||||
<div class="item-desc">
|
||||
<h3>Parliament of Hungary</h3>
|
||||
<p>The Parliament of Hungary, located in Budapest, is a magnificent neo-Gothic building along the Danube River, housing the country's legislature and representing a symbol of Hungary's political and historical significance.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
<div class="item" style="background-image: url(_content/TIAMSharedUI/images/slider2.jpg);">
|
||||
<div class="item-desc">
|
||||
<h3>Buda Castle</h3>
|
||||
<p>Buda Castle, located in Budapest, Hungary, is a historic palace complex that has served as the royal residence and administrative center for Hungarian kings throughout history. </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" style="background-image: url(_content/TIAMSharedUI/images/slider3.jpg);">
|
||||
<div class="item-desc">
|
||||
<h3>Aggtelek National Park</h3>
|
||||
<p>Aggtelek Cave, in northeastern Hungary, is a UNESCO World Heritage site renowned for its intricate karst formations, underground river, and breathtaking natural beauty, making it a must-visit destination for cave enthusiasts and nature lovers.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" style="background-image: url(_content/TIAMSharedUI/images/slider4.jpg);">
|
||||
<div class="item-desc">
|
||||
<h3>Margaret Island</h3>
|
||||
<p>Margaret Island, also in Budapest, is a serene green oasis situated in the middle of the Danube River, offering recreational opportunities, gardens, and a relaxing escape from the city.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" style="background-image: url(_content/TIAMSharedUI/images/slider5.jpg);">
|
||||
<div class="item-desc">
|
||||
<h3>Heroes square</h3>
|
||||
<p>Heroes' Square in Budapest, Hungary, is a grand public square featuring iconic statues and monuments honoring the nation's historic leaders and heroes.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" style="background-image: url(_content/TIAMSharedUI/images/slider6.jpg);">
|
||||
<div class="item-desc">
|
||||
<h3>Vajdahunyad Castle</h3>
|
||||
<p>Vajdahunyad Castle, also in Budapest, is a fairytale-like complex showcasing architectural styles from various historical periods, making it a unique and picturesque cultural destination.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<EventsComponent ItemType="0"></EventsComponent>
|
||||
<FeaturedItems ItemType="0"></FeaturedItems>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(".custom-carousel").owlCarousel({
|
||||
autoWidth: true,
|
||||
loop: true
|
||||
});
|
||||
$(document).ready(function () {
|
||||
$(".custom-carousel .item").click(function () {
|
||||
$(".custom-carousel .item").not($(this)).removeClass("active");
|
||||
$(this).toggleClass("active");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
@using TIAM.Entities.Transfers
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
|
||||
|
||||
<EditForm Model="@Tour" OnValidSubmit="@HandleValidSubmit">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Title</label>
|
||||
<InputText class="form-control" @bind-Value="Tour.Title" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Fancy Description</label>
|
||||
<InputTextArea class="form-control" @bind-Value="Tour.FancyDescription" rows="4" />
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">Save</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="HandleCancel">Cancel</button>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
@code {
|
||||
[Parameter] public TourInfo Tour { get; set; } = new();
|
||||
[Parameter] public EventCallback<TourInfo> OnSave { get; set; }
|
||||
[Parameter] public EventCallback OnCancel { get; set; }
|
||||
|
||||
private async Task HandleValidSubmit()
|
||||
{
|
||||
await OnSave.InvokeAsync(Tour);
|
||||
}
|
||||
|
||||
private async Task HandleCancel()
|
||||
{
|
||||
await OnCancel.InvokeAsync(Tour);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
@page "/signature-ride-packages"
|
||||
@inject TourService TourService
|
||||
@using TIAMSharedUI.Shared
|
||||
@using TIAMSharedUI.Shared.Components
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
|
||||
<HeroSlider SliderItems="@sliders" PBottom="50px" Height="30vh"></HeroSlider>
|
||||
|
||||
|
||||
|
||||
<ToursComponent />
|
||||
@* <FeaturedItems ItemType="0" /> *@
|
||||
|
||||
|
||||
@code {
|
||||
public List<HeroSliderItem> sliders = new()
|
||||
{
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Explore Our Programs",
|
||||
ButtonUrl= "/signature-ride-packages"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Book now",
|
||||
ButtonUrl= "/transfer"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "",
|
||||
ButtonUrl= ""
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
@page "/book-a-tour/{TransferDestinationId}/{PriceCategory:int}"
|
||||
@using AyCode.Core.Consts
|
||||
@using AyCode.Core.Helpers
|
||||
@using TIAM.Models.Dtos.Users
|
||||
@using TIAM.Services
|
||||
@using TIAMSharedUI.Pages.Components
|
||||
@using TIAMSharedUI.Pages.Components.EditComponents
|
||||
@using TIAMSharedUI.Shared
|
||||
@using TIAMSharedUI.Shared.Components.BaseComponents
|
||||
@using TIAMWebApp.Shared.Application.Interfaces
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI.WizardModels
|
||||
@using AyCode.Services.Loggers
|
||||
@using TIAMSharedUI.Pages.User.Hotels
|
||||
@using TIAMWebApp.Shared.Application.Models.PageModels
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@using TIAMWebApp.Shared.Application.Utility
|
||||
@inherits BasePageComponent
|
||||
@inject NavigationManager navManager
|
||||
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
|
||||
@inject IWizardProcessor WizardProcessor
|
||||
@inject IUserDataService UserDataService
|
||||
@inject AdminSignalRClient _adminSignalRClient
|
||||
@inject ITransferDataService TransferDataService
|
||||
@inject TourService TourService
|
||||
|
||||
<PageTitle>Transfer</PageTitle>
|
||||
|
||||
<HeroSlider SliderItems="sliders" Height="30vh"></HeroSlider>
|
||||
<div class="container-fluid" style="position: relative; z-index: 2;">
|
||||
<div class="row d-flex justify-content-center">
|
||||
|
||||
@{
|
||||
if (_displayHelp)
|
||||
{
|
||||
<div class="col-md-6 col-12 px-5">
|
||||
<!-- Step 1 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 1: Choose Your Transfer Direction
|
||||
</p>
|
||||
<p class="text-muted">At the top of the form, select whether you need a transfer <strong>"To the Airport"</strong> or <strong>"From the Airport"</strong> by clicking on the corresponding tab.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
|
||||
Step 2: Enter the Destination (or Pickup) Address
|
||||
|
||||
</p>
|
||||
<p class="text-muted">In the <strong>PickupAddress</strong> section, select your address:</p>
|
||||
<ul>
|
||||
<li><strong>Preset addresses:</strong> Click on the dropdown menu under “Preset addresses” and choose an address from the list. For example, you may see options like "Széchenyi fürdő."</li>
|
||||
<li><strong>Custom address:</strong> If your address is not listed, click on the "Custom address" tab to manually enter your address.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 3: Confirm the Destination
|
||||
</p>
|
||||
<p class="text-muted">Once you select or enter the address, the form will display it as the "Selected address." Make sure this is correct before proceeding.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 4: Enter Flight Information (Optional)
|
||||
</p>
|
||||
<p class="text-muted">If applicable, fill in your <strong>FlightNumber</strong>. This is optional, so you can leave it blank if you don't have or don’t want to provide it.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 5 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 5: Specify the Number of Passengers
|
||||
</p>
|
||||
<p>In the <strong>NumberOfPassengers</strong> field, enter the number of people who will be traveling. The default is set to 1, but you can change it as needed.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 6 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 6: Indicate the Amount of Luggage
|
||||
</p>
|
||||
<p class="text-muted">In the <strong>NumberOfLuggage</strong> field, enter the total number of luggage items you will be bringing.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 7 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 7: Fill in Your Personal Information
|
||||
</p>
|
||||
<p class="text-muted">Under <strong>FullName</strong>, enter your first and last name in the respective fields. Provide your <strong>PhoneNumber</strong> in the designated field. The phone number appears to be pre-filled with a sample number ("+11234567890"), so be sure to update it with your actual contact number. Enter your <strong>EmailAddress</strong> to receive confirmation and any further communication regarding your transfer.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 8 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 8: Add Additional Comments (Optional)
|
||||
</p>
|
||||
<p class="text-muted">If you have any special requests or additional information you’d like to provide, use the <strong>Comment</strong> section to do so.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 9 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 9: Submit Your Request
|
||||
</p>
|
||||
<p>Once all fields are filled in correctly, click the <strong>Submit</strong> button at the bottom of the form to place your transfer order.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 10 -->
|
||||
<div class="card mb-3 shadow-sm">
|
||||
|
||||
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Step 10: Confirmation
|
||||
</p>
|
||||
|
||||
<p>After submitting, you should receive a confirmation email or message. Ensure all the details are correct, and you’re all set!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<DxToolbar ItemRenderStyleMode="ToolbarRenderStyleMode.Contained">
|
||||
<Items>
|
||||
<DxToolbarItem Alignment="ToolbarItemAlignment.Right" Text="Help" RenderStyle="ButtonRenderStyle.Secondary" IconCssClass="grid-icon-column-chooser" Click="ShowHelp_Click" />
|
||||
</Items>
|
||||
</DxToolbar>
|
||||
<div style="max-height: 300px; overflow-y: hidden">
|
||||
<img class="img-fluid" src="@tourInfo.CoverImageUrl" alt="@tourInfo.Title"/>
|
||||
</div>
|
||||
<DynamicEditForm Data="_myModel" TitleString="@($"To: {tourInfo.Title}, Price: {_myModel.Price} EUR")" isEditing="true" IgnoreReflection="_transferIgnorList1" OnSubmit="SubmitForm"></DynamicEditForm>
|
||||
|
||||
<InputWizard Data=@_myModel
|
||||
OnSubmit="SubmitForm"
|
||||
IgnoreReflection="@_transferIgnorList1"
|
||||
SubmitButtonText="ButtonSend"
|
||||
TitleResourceString="TransferTitle"
|
||||
SubtitleResourceString="TransferSubtitle"></InputWizard>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-12 col-sm-6 p-5">
|
||||
<h1>Book an Airport Transfer</h1>
|
||||
<p>Welcome to Tour I Am! Book your airport transfer with us for a smooth and stress-free experience. Our professional drivers are ready to take you to and from the airport in comfort and style. We offer competitive rates and reliable service, ensuring you get to your destination on time.</p>
|
||||
|
||||
<h2>Why Choose Tour I Am?</h2>
|
||||
<ul class="list-unstyled">
|
||||
<li><strong>Reliable Service:</strong> Punctual pickups and drop-offs.</li>
|
||||
<li><strong>Professional Drivers:</strong> Experienced and courteous drivers.</li>
|
||||
<li><strong>Affordable Rates:</strong> Competitive pricing with no hidden fees.</li>
|
||||
<li><strong>Comfortable Vehicles:</strong> Clean, modern, and well-maintained cars.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 p-5">
|
||||
<img class="img-fluid" src="_content/TIAMSharedUI/images/about1.jpg" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 p-5">
|
||||
<img class="img-fluid" src="_content/TIAMSharedUI/images/about2.jpg" />
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 p-5">
|
||||
|
||||
<h2>How to Book</h2>
|
||||
<p>Booking your airport transfer is easy! Simply visit our <a href="/transfer">booking page</a>, enter your details, and confirm your reservation. You can also contact us at <a href="mailto:info@touriam.com">info@touriam.com</a> or call us at (123) 456-7890 for assistance.</p>
|
||||
|
||||
<p>Experience the convenience and reliability of Tour I Am. Book your airport transfer today and travel with peace of mind!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter] public string TransferDestinationId { get; set; }
|
||||
[Parameter] public int PriceCategory { get; set; } = 1;
|
||||
private LoggerClient<TransferPage> _logger;
|
||||
|
||||
private readonly TransferWizardModel _myModel = new TransferWizardModel();
|
||||
private TourInfo? tourInfo = new();
|
||||
|
||||
private bool _displayHelp = false;
|
||||
|
||||
public List<HeroSliderItem> sliders = new List<HeroSliderItem>
|
||||
{
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1551867633-194f125bddfa?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Explore Our Programs",
|
||||
ButtonUrl= "/signature-ride-packages"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "Discover the freedom of personalized travel with expert private transfers and curated inspiration.",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1549877452-9c387954fbc2?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "Book now",
|
||||
ButtonUrl= "/transfer"
|
||||
},
|
||||
new HeroSliderItem
|
||||
{
|
||||
Title = "Experience Hungary on Your Terms",
|
||||
Subtitle = "",
|
||||
ImageUrl = "https://images.unsplash.com/photo-1507622560124-621e26755fb8?auto=format&fit=crop&q=80&w=2070&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
||||
ButtonText = "",
|
||||
ButtonUrl= ""
|
||||
}
|
||||
};
|
||||
|
||||
private readonly List<string> _transferIgnorList1 =
|
||||
[
|
||||
"Id",
|
||||
"Destination",
|
||||
"UserId",
|
||||
"ProductId",
|
||||
"PaymentId",
|
||||
"FirstName",
|
||||
"LastName",
|
||||
"UserProductMappingId",
|
||||
"UserProductToCarId",
|
||||
"ReferralId",
|
||||
"Price"
|
||||
];
|
||||
|
||||
|
||||
public async Task SubmitForm(object result)
|
||||
{
|
||||
var resModel = (TransferWizardModel)result;
|
||||
|
||||
//let's check if user exists with this email
|
||||
var user = await UserDataService.GetUserByEmailAsync(resModel.EmailAddress!);
|
||||
if (user != null && user.Id != Guid.Empty)
|
||||
{
|
||||
resModel.UserId = user.Id;
|
||||
//user exists already
|
||||
|
||||
if (_sessionService.User != null)
|
||||
{
|
||||
if (_sessionService.User.UserId == user.Id)
|
||||
{
|
||||
|
||||
//I have ordered for myself
|
||||
resModel.ReferralId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if I am logged in and different user I become referrer (if no referrer already)
|
||||
var transferUserDetail = await UserDataService.GetUserDetailByIdAsync(user.Id);
|
||||
var userDetail = await UserDataService.GetUserDetailByIdAsync(_sessionService.User.UserId);
|
||||
|
||||
if (transferUserDetail.UserDto.RefferalId != null)
|
||||
{
|
||||
//user has aready a referrer so we use that
|
||||
resModel.ReferralId = transferUserDetail.UserDto.RefferalId;
|
||||
}
|
||||
else
|
||||
{
|
||||
//user has no referrer so I am the referrer
|
||||
resModel.ReferralId = userDetail.UserDto.RefferalId;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//create a guest user and set referralId
|
||||
var registration = new RegistrationModel();
|
||||
|
||||
var password = AcCharsGenerator.NewPassword(AcConst.MinPasswordLength, 16);
|
||||
|
||||
registration.Email = resModel.EmailAddress;
|
||||
registration.PhoneNumber = resModel.PhoneNumber;
|
||||
registration.Password = password;
|
||||
//get list with one member!
|
||||
|
||||
var createResult = await UserDataService.CreateGuestUser(registration);
|
||||
if (createResult.isSuccess)
|
||||
{
|
||||
if (createResult.user != null)
|
||||
{
|
||||
if (_sessionService.User != null)
|
||||
{
|
||||
//if I am logged in user I become referrer
|
||||
var userDetail = await UserDataService.GetUserDetailByIdAsync(_sessionService.User.UserId);
|
||||
var createdUserDetail = await UserDataService.GetUserDetailByIdAsync(createResult.user.Id);
|
||||
if (createdUserDetail != null)
|
||||
{
|
||||
createdUserDetail.UserDto.RefferalId = userDetail.UserDto.RefferalId;
|
||||
|
||||
var updatedNewUser = await _adminSignalRClient.UpdateUserModelDtoDetail(userDetail);
|
||||
if (updatedNewUser != null)
|
||||
{
|
||||
//referral set
|
||||
}
|
||||
else
|
||||
{
|
||||
//something wrong
|
||||
}
|
||||
}
|
||||
|
||||
resModel.ReferralId = userDetail.UserDto.RefferalId;
|
||||
}
|
||||
|
||||
resModel.UserId = createResult.user.Id;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//some error handling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var transfer = await WizardProcessor.ProcessWizardAsync<TransferWizardModel>(result.GetType(), result);
|
||||
_logger.Info($"Submitted nested form: {result.GetType().FullName}");
|
||||
navManager.NavigateTo($"/mytransfers/{resModel.Id}");
|
||||
}
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
_logger = new LoggerClient<TransferPage>(LogWriters.ToArray());
|
||||
|
||||
|
||||
return base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
//get transferDestination
|
||||
var destination = await TransferDataService.GetTransferDestinationbyIdAsync(Guid.Parse(TransferDestinationId));
|
||||
_myModel.Destination = destination.AddressString;
|
||||
switch (PriceCategory)
|
||||
{
|
||||
case 1:
|
||||
_myModel.Price = destination.Price;
|
||||
break;
|
||||
case 2:
|
||||
_myModel.Price = destination.Price2;
|
||||
break;
|
||||
case 3:
|
||||
_myModel.Price = destination.Price3;
|
||||
break;
|
||||
}
|
||||
|
||||
tourInfo = await TourService.GetAsync(destination.Id);
|
||||
|
||||
|
||||
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
private void ShowHelp_Click()
|
||||
{
|
||||
_displayHelp = !_displayHelp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
.container {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
width: 750px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.container {
|
||||
width: 970px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.container {
|
||||
width: 1170px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#featureContainer .carousel-inner .carousel-item > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#featureContainer .carousel-inner .carousel-item > div:first-child {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
#featureContainer .carousel-inner .carousel-item.active,
|
||||
#featureContainer .carousel-inner .carousel-item-next,
|
||||
#featureContainer .carousel-inner .carousel-item-prev {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||
#featureContainer .carousel-inner .carousel-item-end.active,
|
||||
#featureContainer .carousel-inner .carousel-item-next {
|
||||
transform: translateX(25%);
|
||||
}
|
||||
|
||||
#featureContainer .carousel-inner .carousel-item-start.active,
|
||||
#featureContainer .carousel-inner .carousel-item-prev {
|
||||
transform: translateX(-25%);
|
||||
}
|
||||
|
||||
#featureContainer .card img {
|
||||
width: 90%;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
#featureContainer .carousel-item {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#featureContainer .card img {
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
}
|
||||
}
|
||||
|
||||
#featureContainer .carousel-inner .carousel-item-end,
|
||||
#featureContainer .carousel-inner .carousel-item-start {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#featureContainer .card {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#featureContainer .card {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#featureContainer .card .card-img-overlays {
|
||||
position: absolute;
|
||||
bottom: 15%;
|
||||
left: 10%;
|
||||
}
|
||||
|
||||
#featureContainer a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#featureContainer .indicator {
|
||||
border: 1px solid rgb(202, 202, 202);
|
||||
padding: 3px 6px 3px 6px;
|
||||
}
|
||||
|
||||
#featureContainer .indicator:hover {
|
||||
background-color: blue;
|
||||
border: 1px solid blue;
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
#featureContainer .indicator:hover {
|
||||
color: white;
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
#featureContainer .indicator {
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
#featureContainer .float-end {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Reseting */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 800px;
|
||||
min-height: 500px;
|
||||
margin: 10px auto;
|
||||
padding: 30px 30px 30px 30px;
|
||||
/*background-color: #ecf0f3;*/
|
||||
border-radius: 15px;
|
||||
/*box-shadow: 13px 13px 20px #cbced1, -13px -13px 20px #fff;*/
|
||||
}
|
||||
|
||||
|
||||
.wrapper .name {
|
||||
font-weight: 600;
|
||||
font-size: 1.4rem;
|
||||
letter-spacing: 1.3px;
|
||||
padding-left: 10px;
|
||||
/*color: #555*/;
|
||||
}
|
||||
|
||||
.wrapper .form-field input {
|
||||
width: 100%;
|
||||
display: block;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
font-size: 1.2rem;
|
||||
color: #666;
|
||||
padding: 10px 15px 10px 10px;
|
||||
/* border: 1px solid red; */
|
||||
}
|
||||
|
||||
.wrapper .form-field {
|
||||
padding-left: 10px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid;
|
||||
/*border-radius: 20px;*/
|
||||
//*ox-shadow: inset 3px 3px 3px #cbced1, inset -3px -3px 3px #fff;*/
|
||||
}
|
||||
|
||||
.wrapper .form-field .fas {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.wrapper .btn {
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
/*background-color: #03A9F4;*/
|
||||
color: #fff;
|
||||
border-radius: 15px;
|
||||
/*box-shadow: 3px 3px 3px #b1b1b1, -3px -3px 3px #fff;*/
|
||||
letter-spacing: 1.3px;
|
||||
}
|
||||
|
||||
.wrapper .btn:hover {
|
||||
background-color: #039BE5;
|
||||
}
|
||||
|
||||
.wrapper a {
|
||||
text-decoration: none;
|
||||
font-size: 0.8rem;
|
||||
color: #03A9F4;
|
||||
}
|
||||
|
||||
.wrapper a:hover {
|
||||
color: #039BE5;
|
||||
}
|
||||
|
||||
@media(max-width: 380px) {
|
||||
.wrapper {
|
||||
margin: 30px 20px;
|
||||
padding: 40px 15px 15px 15px;
|
||||
}
|
||||
}
|
||||
|
|
@ -267,8 +267,7 @@
|
|||
"Destination",
|
||||
"UserId",
|
||||
"ProductId",
|
||||
"PaymentId",
|
||||
"TripDate",
|
||||
"PaymentId",
|
||||
"FirstName",
|
||||
"LastName",
|
||||
"UserProductMappingId",
|
||||
|
|
@ -283,8 +282,7 @@
|
|||
"PickupAddress",
|
||||
"UserId",
|
||||
"ProductId",
|
||||
"PaymentId",
|
||||
"TripDate",
|
||||
"PaymentId",
|
||||
"FirstName",
|
||||
"LastName",
|
||||
"UserProductMappingId",
|
||||
|
|
@ -405,7 +403,7 @@
|
|||
|
||||
var transfer = await WizardProcessor.ProcessWizardAsync<TransferWizardModel>(result.GetType(), result);
|
||||
_logger.Info($"Submitted nested form: {result.GetType().FullName}");
|
||||
navManager.NavigateTo($"/transfer2/{resModel.Id}");
|
||||
navManager.NavigateTo($"/mytransfers/{resModel.Id}");
|
||||
}
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
void OnPasswordSet(string password)
|
||||
{
|
||||
msg = $"Password to set: {NewPassword}";
|
||||
msg = $"Please type in again";
|
||||
PasswordNotSet = false;
|
||||
|
||||
StateHasChanged();
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="Appointment" SortOrder="GridColumnSortOrder.Descending" GroupIndex="0" GroupInterval="GridColumnGroupInterval.Custom" DisplayFormat="g" Width="125" />
|
||||
<DxGridDataColumn FieldName="FullName" />
|
||||
<DxGridDataColumn FieldName="ContactPhone" Width="120" />
|
||||
<DxGridDataColumn FieldName="ContactEmail" Width="120" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
@page "/sysadmin/blogs"
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@using TIAMSharedUI.Shared
|
||||
@layout AdminLayout
|
||||
@inject BlogService BlogService
|
||||
|
||||
<div clss="container">
|
||||
<h3 class="mb-4">Manage Blog Posts</h3>
|
||||
|
||||
<EditForm Model="@Post" OnValidSubmit="@SavePost">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Title</label>
|
||||
<InputText class="form-control" @bind-Value="Post.Title" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Lead</label>
|
||||
<InputText class="form-control" @bind-Value="Post.Lead" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Google Drive Link</label>
|
||||
<InputText class="form-control" @bind-Value="Post.DriveLink" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Tags (comma-separated)</label>
|
||||
<InputText class="form-control" @bind-Value="TagsCsv" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Cover Image (optional)</label>
|
||||
<InputFile OnChange="@HandleFileSelected" />
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit" disabled="@IsSaving">
|
||||
@if (IsSaving)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm"></span> @(IsEditMode ? "Updating..." : "Saving...")
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@(IsEditMode ? "Update Post" : "Save Post")</span>
|
||||
}
|
||||
</button>
|
||||
|
||||
@if (IsEditMode)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary ms-2" @onclick="CancelEdit">Cancel</button>
|
||||
}
|
||||
</EditForm>
|
||||
|
||||
@if (SaveSuccess)
|
||||
{
|
||||
<div class="alert alert-success mt-3">Post saved successfully!</div>
|
||||
}
|
||||
|
||||
<h4 class="mt-5">Existing Posts</h4>
|
||||
|
||||
@if (Posts.Count == 0)
|
||||
{
|
||||
<p>No blog posts found.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-bordered mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Tags</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Posts)
|
||||
{
|
||||
<tr>
|
||||
<td><img src="@item.CoverImage" style="max-height:150px" /></td>
|
||||
<td>@item.Title</td>
|
||||
<td>@string.Join(", ", item.Tags)</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-primary me-2" @onclick="() => EditPost(item)">Edit</button>
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DeletePost(item.Id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private BlogPostMetadata Post = new();
|
||||
private List<BlogPostMetadata> Posts = new();
|
||||
private IBrowserFile? CoverImage;
|
||||
private string TagsCsv = "";
|
||||
private bool IsSaving = false;
|
||||
private bool SaveSuccess = false;
|
||||
private bool IsEditMode = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadPosts();
|
||||
}
|
||||
|
||||
private async Task LoadPosts()
|
||||
{
|
||||
Posts = await BlogService.GetAllPostsAsync();
|
||||
}
|
||||
|
||||
private async Task HandleFileSelected(InputFileChangeEventArgs e)
|
||||
{
|
||||
CoverImage = e.File;
|
||||
}
|
||||
|
||||
private async Task SavePost()
|
||||
{
|
||||
IsSaving = true;
|
||||
SaveSuccess = false;
|
||||
|
||||
Post.Tags = TagsCsv.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList();
|
||||
|
||||
if (IsEditMode)
|
||||
{
|
||||
await BlogService.UpdatePostAsync(Post, CoverImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
await BlogService.CreatePostAsync(Post, CoverImage);
|
||||
}
|
||||
|
||||
IsSaving = false;
|
||||
SaveSuccess = true;
|
||||
|
||||
await LoadPosts();
|
||||
ResetForm();
|
||||
}
|
||||
|
||||
private void EditPost(BlogPostMetadata post)
|
||||
{
|
||||
Post = new BlogPostMetadata
|
||||
{
|
||||
Id = post.Id,
|
||||
Title = post.Title,
|
||||
Lead = post.Lead,
|
||||
DriveLink = post.DriveLink,
|
||||
Tags = new List<string>(post.Tags),
|
||||
CoverImage = post.CoverImage
|
||||
};
|
||||
TagsCsv = string.Join(", ", post.Tags);
|
||||
IsEditMode = true;
|
||||
SaveSuccess = false;
|
||||
}
|
||||
|
||||
private async Task DeletePost(string id)
|
||||
{
|
||||
if (await ConfirmDeleteAsync())
|
||||
{
|
||||
await BlogService.DeletePostAsync(id);
|
||||
await LoadPosts();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> ConfirmDeleteAsync()
|
||||
{
|
||||
return await Task.FromResult(true); // Replace with real confirmation popup later
|
||||
}
|
||||
|
||||
private void CancelEdit()
|
||||
{
|
||||
ResetForm();
|
||||
}
|
||||
|
||||
private void ResetForm()
|
||||
{
|
||||
Post = new BlogPostMetadata();
|
||||
TagsCsv = "";
|
||||
CoverImage = null;
|
||||
IsEditMode = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
private static DateTime _toDate = DateTime.Today;
|
||||
|
||||
private static int _takeCount = 250;
|
||||
private object[] _contextParams = new object[3] { _takeCount, _fromDate, _toDate };
|
||||
private object[] _contextParams = [_takeCount, _fromDate, _toDate];
|
||||
|
||||
private LoggerClient<LogViewerGridComponent> _logger;
|
||||
private static List<LogLevel> _selectedLogLevels = [LogLevel.Error, LogLevel.Warning, LogLevel.Suggest];
|
||||
|
|
@ -154,12 +154,12 @@
|
|||
|
||||
if (_selectedLogLevels.Count > 0)
|
||||
{
|
||||
filterCriteria = new InOperator(nameof(LogLevel), _selectedLogLevels);
|
||||
filterCriteria = new InOperator(nameof(LogItemViewerModel.LogLevel), _selectedLogLevels);
|
||||
filterText = GetFilterText(_selectedLogLevels);
|
||||
}
|
||||
|
||||
_filterText = filterText;
|
||||
_logViewerGrid.SetFieldFilterCriteria(nameof(LogLevel), filterCriteria);
|
||||
_logViewerGrid.SetFieldFilterCriteria(nameof(LogItemViewerModel.LogLevel), filterCriteria);
|
||||
}
|
||||
|
||||
private async Task OnValueChangedTakeCount(int value)
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
{
|
||||
if (e.ElementType != GridElementType.DataRow) return;
|
||||
|
||||
var logLevelObject = e.Grid?.GetRowValue(e.VisibleIndex, nameof(LogLevel));
|
||||
var logLevelObject = e.Grid?.GetRowValue(e.VisibleIndex, nameof(LogItemViewerModel.LogLevel));
|
||||
if (logLevelObject == null) return;
|
||||
|
||||
var levelObject = (LogLevel)logLevelObject;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
@using TIAM.Core.Enums
|
||||
@using TIAM.Entities.Emails
|
||||
@using TIAM.Entities.Transfers
|
||||
@using TIAM.Entities.Users
|
||||
@using TIAM.Resources
|
||||
@using TIAMSharedUI.Pages.Components
|
||||
@using TIAMSharedUI.Shared
|
||||
|
|
@ -20,8 +21,10 @@
|
|||
@using AyCode.Core
|
||||
@using AyCode.Core.Helpers
|
||||
@using DevExpress.Data.Filtering
|
||||
@using TIAM.Entities.Drivers
|
||||
@using TIAM.Entities.Emails
|
||||
@using TIAMSharedUI.Shared.Components.BaseComponents
|
||||
@using TIAM.Services
|
||||
@inherits UserBasePageComponent
|
||||
@layout AdminLayout
|
||||
@inject IWizardProcessor wizardProcessor
|
||||
|
|
@ -30,465 +33,543 @@
|
|||
<PageTitle>Transfers</PageTitle>
|
||||
|
||||
<div class="text-center m-5">
|
||||
<h1>Transfer management</h1>
|
||||
<h2 style="font-size:small">Manage transfers here!</h2>
|
||||
<h1>Transfer management</h1>
|
||||
<h2 style="font-size:small">Manage transfers here!</h2>
|
||||
</div>
|
||||
|
||||
|
||||
<DxPopup CssClass="popup-demo-events"
|
||||
@bind-Visible="@_popupVisible"
|
||||
ShowFooter="true"
|
||||
CloseOnEscape="true"
|
||||
CloseOnOutsideClick="false"
|
||||
ShowCloseButton="false"
|
||||
HeaderText="MessageBox"
|
||||
Closing="EulaPopupClosing"
|
||||
Closed="EulaPopupClosed">
|
||||
<BodyContentTemplate>
|
||||
<InputWizard Data=@_messageWizardModel
|
||||
OnSubmit="SubmitForm"
|
||||
IgnoreReflection=@IgnoreList
|
||||
TitleResourceString="NewMessage"
|
||||
SubtitleResourceString="NewMessageSubtitle"
|
||||
SubmitButtonText="@_localizer.GetString("ButtonSend")"></InputWizard>
|
||||
</BodyContentTemplate>
|
||||
<FooterContentTemplate Context="Context">
|
||||
<div class="popup-demo-events-footer">
|
||||
<!--DxCheckBox CssClass="popup-demo-events-checkbox" @bind-Checked="@EulaAccepted">I accept the terms of the EULA</!--DxCheckBox-->
|
||||
<!--DxButton CssClass="popup-demo-events-button ms-2" RenderStyle="ButtonRenderStyle.Primary" Text="OK" Click="Context.CloseCallback" /-->
|
||||
<DxButton CssClass="popup-demo-events-button ms-2" RenderStyle="ButtonRenderStyle.Secondary" Text="Cancel" Click="CancelCreateClick" />
|
||||
</div>
|
||||
</FooterContentTemplate>
|
||||
@bind-Visible="@_popupVisible"
|
||||
ShowFooter="true"
|
||||
CloseOnEscape="true"
|
||||
CloseOnOutsideClick="false"
|
||||
ShowCloseButton="false"
|
||||
HeaderText="MessageBox"
|
||||
Closing="EulaPopupClosing"
|
||||
Closed="EulaPopupClosed">
|
||||
<BodyContentTemplate>
|
||||
<InputWizard Data=@_messageWizardModel
|
||||
OnSubmit="SubmitForm"
|
||||
IgnoreReflection=@IgnoreList
|
||||
TitleResourceString="NewMessage"
|
||||
SubtitleResourceString="NewMessageSubtitle"
|
||||
SubmitButtonText="@_localizer.GetString("ButtonSend")"></InputWizard>
|
||||
</BodyContentTemplate>
|
||||
<FooterContentTemplate Context="Context">
|
||||
<div class="popup-demo-events-footer">
|
||||
<!--DxCheckBox CssClass="popup-demo-events-checkbox" @bind-Checked="@EulaAccepted">I accept the terms of the EULA</!--DxCheckBox-->
|
||||
<!--DxButton CssClass="popup-demo-events-button ms-2" RenderStyle="ButtonRenderStyle.Primary" Text="OK" Click="Context.CloseCallback" /-->
|
||||
<DxButton CssClass="popup-demo-events-button ms-2" RenderStyle="ButtonRenderStyle.Secondary" Text="Cancel" Click="CancelCreateClick" />
|
||||
</div>
|
||||
</FooterContentTemplate>
|
||||
</DxPopup>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class=" col-12">
|
||||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<div class="card">
|
||||
<div class="row">
|
||||
<div class=" col-12">
|
||||
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
|
||||
<div class="card">
|
||||
|
||||
<DxTabs>
|
||||
<DxTabs>
|
||||
|
||||
<DxTabPage Text="DataGrid">
|
||||
<div class="d-flex flex-column mb-4 pb-2">
|
||||
<div class="align-self-end pl-2 pb-2">
|
||||
<DxButton Text="Column Chooser"
|
||||
RenderStyle="ButtonRenderStyle.Secondary"
|
||||
IconCssClass="btn-column-chooser"
|
||||
Click="ColumnChooserButton_Click" />
|
||||
</div>
|
||||
<DxTabPage Text="DataGrid">
|
||||
<div class="d-flex flex-column mb-4 pb-2">
|
||||
<div class="align-self-end pl-2 pb-2">
|
||||
<DxButton Text="Column Chooser"
|
||||
RenderStyle="ButtonRenderStyle.Secondary"
|
||||
IconCssClass="btn-column-chooser"
|
||||
Click="ColumnChooserButton_Click" />
|
||||
</div>
|
||||
|
||||
<TransferGrid @ref="_gridTransfer"
|
||||
Logger="_logger"
|
||||
SignalRClient="AdminSignalRClient"
|
||||
FilterText="@_filterText"
|
||||
OnDataSourceChanged="DataSourceChanged"
|
||||
OnGridItemChanging="DataSourceItemChanging"
|
||||
OnGridItemChanged="DataSourceItemChanged"
|
||||
OnGridItemDeleting="DataItemDeleting"
|
||||
OnGridEditModelSaving="DataItemSaving"
|
||||
CustomizeElement="Grid_CustomizeElement"
|
||||
CustomizeEditModel="Grid_CustomizeEditModel"
|
||||
EditMode="GridEditMode.EditForm"
|
||||
ColumnResizeMode="GridColumnResizeMode.NextColumn"
|
||||
PageSize="13"
|
||||
ShowFilterRow="true">
|
||||
<TransferGrid @ref="_gridTransfer"
|
||||
Logger="_logger"
|
||||
SignalRClient="AdminSignalRClient"
|
||||
FilterText="@_filterText"
|
||||
OnDataSourceChanged="DataSourceChanged"
|
||||
OnGridItemChanging="DataSourceItemChanging"
|
||||
OnGridItemChanged="DataSourceItemChanged"
|
||||
OnGridItemDeleting="DataItemDeleting"
|
||||
OnGridEditModelSaving="DataItemSaving"
|
||||
SelectedDataItemChanged="OnSelectedDataItemChanged"
|
||||
CustomizeElement="Grid_CustomizeElement"
|
||||
CustomizeEditModel="Grid_CustomizeEditModel"
|
||||
EditMode="GridEditMode.EditForm"
|
||||
ColumnResizeMode="GridColumnResizeMode.NextColumn"
|
||||
PageSize="13"
|
||||
ShowFilterRow="true">
|
||||
|
||||
<Columns>
|
||||
<DxGridCommandColumn NewButtonVisible="false" DeleteButtonVisible="AcDomain.IsDeveloperVersion" Width="80" MinWidth="80" FixedPosition="GridColumnFixedPosition.Left" />
|
||||
<DxGridDataColumn FieldName="Id" ShowInColumnChooser="AcDomain.IsDeveloperVersion" Visible="AcDomain.IsDeveloperVersion" DisplayFormat="N" />
|
||||
<DxGridDataColumn FieldName="OrderId" Caption="Order" SortIndex="1" SortOrder="GridColumnSortOrder.Descending" Width="70">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var idKeyField = ((Transfer)context.DataItem).Id.ToString("N");
|
||||
var editUri = $"mytransfers/{idKeyField}";
|
||||
<NavLink href="@editUri">
|
||||
<text>@context.Value</text>
|
||||
</NavLink>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="FromAddress" />
|
||||
<DxGridDataColumn FieldName="ToAddress" />
|
||||
<DxGridDataColumn FieldName="Appointment" DisplayFormat="g" Width="125" />
|
||||
<DxGridDataColumn FieldName="PassengerCount" Caption="Passengers" Width="90" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="LuggageCount" Caption="Luggages" Width="80" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="FlightNumber" Caption="FlightNum" Width="95" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="Price" Caption="Price" Width="70" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="Revenue" Caption="Revenue" Width="70" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="FullName" />
|
||||
<DxGridDataColumn FieldName="ContactPhone" Width="120" />
|
||||
<DxGridDataColumn FieldName="ContactEmail" Width="120">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var keyField = context.Value;
|
||||
var keyItem = (Transfer)context.DataItem;
|
||||
string buttonText = "Contact";
|
||||
<DxButton Click="() => SendMail(keyItem)" Text="@buttonText" RenderStyle="ButtonRenderStyle.Primary" />
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="PaymentId" DisplayFormat="N" Visible="false" />
|
||||
<DxGridDataColumn Caption="Paid" FieldName="Paid" Width="75" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="TransferStatusType" Caption="Status" SortIndex="0" Width="120" SortOrder="GridColumnSortOrder.Ascending" SortMode="GridColumnSortMode.Value">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
<Columns>
|
||||
<DxGridCommandColumn NewButtonVisible="false" DeleteButtonVisible="AcDomain.IsDeveloperVersion" Width="80" MinWidth="80" FixedPosition="GridColumnFixedPosition.Left" />
|
||||
<DxGridDataColumn FieldName="Id" ShowInColumnChooser="AcDomain.IsDeveloperVersion" Visible="AcDomain.IsDeveloperVersion" DisplayFormat="N" />
|
||||
<DxGridDataColumn FieldName="OrderId" Caption="Order" SortIndex="1" SortOrder="GridColumnSortOrder.Descending" Width="70">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var idKeyField = ((Transfer)context.DataItem).Id.ToString("N");
|
||||
var editUri = $"mytransfers/{idKeyField}";
|
||||
<NavLink href="@editUri">
|
||||
<text>@context.Value</text>
|
||||
</NavLink>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="FromAddress" />
|
||||
<DxGridDataColumn FieldName="ToAddress" />
|
||||
<DxGridDataColumn FieldName="Appointment" DisplayFormat="g" Width="125" />
|
||||
<DxGridDataColumn FieldName="PassengerCount" Caption="Passengers" Width="90" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="LuggageCount" Caption="Luggages" Width="80" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="FlightNumber" Caption="FlightNum" Width="95" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="Price" Caption="Price" Width="70" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="Revenue" Caption="Revenue" Width="70" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="FullName" />
|
||||
<DxGridDataColumn Caption="Driver" Width="120">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var keyItem = (Transfer)context.DataItem;
|
||||
<text>@(string.Join(", ", keyItem.TransferToDrivers.Select(x => x.UserProductMapping?.User?.Profile?.GetFullName())))</text>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
|
||||
TransferStatusModel keyField = TransferStatusModel.GetStatusModel((TransferStatusType)context.Value);
|
||||
string transferStatusText = keyField.StatusName;
|
||||
<text>@transferStatusText</text>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="ReferralId" DisplayFormat="N" Visible="false" />
|
||||
<DxGridDataColumn FieldName="Comment" Caption="Comment" />
|
||||
<DxGridDataColumn FieldName="Created" DisplayFormat="g" Width="125" Visible="false" CaptionAlignment="GridTextAlignment.Center" TextAlignment="GridTextAlignment.Center" />
|
||||
</Columns>
|
||||
<DetailRowTemplate>
|
||||
<DxTabs>
|
||||
<DxTabPage Text="Messages">
|
||||
<MessageDetailGridComponent ContextId="((Transfer)context.DataItem).Id" />
|
||||
</DxTabPage>
|
||||
<DxTabPage Text="Driver">
|
||||
<TransferToDriverGridComponent ContextId="((Transfer)context.DataItem).Id" ParentData="(Transfer)context.DataItem" />
|
||||
</DxTabPage>
|
||||
</DxTabs>
|
||||
</DetailRowTemplate>
|
||||
<EditFormTemplate Context="editFormContext">
|
||||
@{
|
||||
var transfer2 = (Transfer)editFormContext.EditModel;
|
||||
}
|
||||
<DxFormLayout CssClass="w-100">
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.FirstName) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("FirstName")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.LastName) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("LastName")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.DestinationAddress) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("ToAddress")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.PickupAddress) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("FromAddress")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Trip date:" ColSpanMd="3">
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="ContactPhone" Width="120" />
|
||||
<DxGridDataColumn FieldName="ContactEmail" Width="120" />
|
||||
|
||||
<DxDateEdit @bind-Date="@transfer2.Appointment"
|
||||
TimeSectionVisible="true"
|
||||
TimeSectionScrollPickerFormat="tt h m">
|
||||
</DxDateEdit>
|
||||
<DxGridDataColumn FieldName="ContactEmail" Width="120">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
var keyItem = (Transfer)context.DataItem;
|
||||
var buttonText = "Contact";
|
||||
<DxButton Click="() => SendMail(keyItem)" Text="@buttonText" RenderStyle="ButtonRenderStyle.Primary" />
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="PaymentId" DisplayFormat="N" Visible="false" />
|
||||
<DxGridDataColumn Caption="Paid" FieldName="Paid" Width="75" TextAlignment="GridTextAlignment.Center" CaptionAlignment="GridTextAlignment.Center" />
|
||||
<DxGridDataColumn FieldName="TransferStatusType" Caption="Status" SortIndex="0" Width="120" SortOrder="GridColumnSortOrder.Ascending" SortMode="GridColumnSortMode.Value">
|
||||
<CellDisplayTemplate>
|
||||
@{
|
||||
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Passengers:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("PassengerCount")
|
||||
</DxFormLayoutItem>
|
||||
var keyField = TransferStatusModel.GetStatusModel((TransferStatusType)context.Value);
|
||||
var transferStatusText = keyField.StatusName;
|
||||
<text>@transferStatusText</text>
|
||||
}
|
||||
</CellDisplayTemplate>
|
||||
</DxGridDataColumn>
|
||||
<DxGridDataColumn FieldName="ReferralId" DisplayFormat="N" Visible="false" />
|
||||
<DxGridDataColumn FieldName="Comment" Caption="Comment" />
|
||||
<DxGridDataColumn FieldName="Created" DisplayFormat="g" Width="125" Visible="false" CaptionAlignment="GridTextAlignment.Center" TextAlignment="GridTextAlignment.Center" />
|
||||
</Columns>
|
||||
<DetailRowTemplate>
|
||||
<DxTabs>
|
||||
<DxTabPage Text="Messages">
|
||||
<MessageDetailGridComponent ContextId="((Transfer)context.DataItem).Id" />
|
||||
</DxTabPage>
|
||||
<DxTabPage Text="Driver">
|
||||
<TransferToDriverGridComponent ContextId="((Transfer)context.DataItem).Id" ParentData="(Transfer)context.DataItem" />
|
||||
</DxTabPage>
|
||||
</DxTabs>
|
||||
</DetailRowTemplate>
|
||||
<EditFormTemplate Context="editFormContext">
|
||||
@{
|
||||
var transfer2 = (Transfer)editFormContext.EditModel;
|
||||
}
|
||||
<DxFormLayout CssClass="w-100">
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.FirstName) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("FirstName")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.LastName) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("LastName")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.EmailAddress) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("ContactEmail")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.DestinationAddress) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("ToAddress")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption=@_localizer.GetString(ResourceKeys.PickupAddress) ColSpanMd="6">
|
||||
@editFormContext.GetEditor("FromAddress")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Trip date:" ColSpanMd="3">
|
||||
|
||||
<DxDateEdit @bind-Date="@transfer2.Appointment"
|
||||
TimeSectionVisible="true"
|
||||
TimeSectionScrollPickerFormat="tt h m">
|
||||
</DxDateEdit>
|
||||
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Passengers:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("PassengerCount")
|
||||
</DxFormLayoutItem>
|
||||
|
||||
|
||||
<DxFormLayoutItem Caption="Paid:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("Payed")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Paid:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("Payed")
|
||||
</DxFormLayoutItem>
|
||||
|
||||
<DxFormLayoutItem Caption="Status:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("TransferStatusType")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Price:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("Price")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Status:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("TransferStatusType")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Price:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("Price")
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Revenue:" ColSpanMd="3">
|
||||
@editFormContext.GetEditor("Revenue")
|
||||
</DxFormLayoutItem>
|
||||
|
||||
</DxFormLayout>
|
||||
</EditFormTemplate>
|
||||
</DxFormLayout>
|
||||
</EditFormTemplate>
|
||||
|
||||
<ToolbarTemplate>
|
||||
<div>
|
||||
<DxTagBox Data="@TransferStatusModel.AllStatuses.Values" Values="@_selectedCategories" @ref="_filterTag"
|
||||
ValuesChanged="(IEnumerable<TransferStatusModel> values) => TagBox_ValuesChanged(values)"
|
||||
ValueFieldName="StatusValue" TextFieldName="StatusName" NullText="Select status type..."
|
||||
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" aria-label="Select status type" />
|
||||
</div>
|
||||
</ToolbarTemplate>
|
||||
</TransferGrid>
|
||||
</div>
|
||||
</DxTabPage>
|
||||
<ToolbarTemplate>
|
||||
<div>
|
||||
<DxTagBox Data="@(Enum.GetValues<TransferStatusType>().ToList())" Values="@_selectedCategories"
|
||||
NullText="Select status type..." ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" aria-label="Select status type"
|
||||
ValuesChanged="(IEnumerable<TransferStatusType> values) => TagBox_ValuesChanged(values)" />
|
||||
|
||||
<DxTabPage Text="Calendar">
|
||||
<div class="d-flex flex-column mb-4 pb-2">
|
||||
<DxScheduler @bind-StartDate="@StartDate"
|
||||
DataStorage="@_dataStorage"
|
||||
CssClass="w-100">
|
||||
<DxSchedulerTimelineView Duration="@TimeSpan.FromHours(48)" CellMinWidth="80">
|
||||
<Scales>
|
||||
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Day" UnitCount="1"></DxSchedulerTimeScale>
|
||||
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Hour" UnitCount="2"></DxSchedulerTimeScale>
|
||||
</Scales>
|
||||
</DxSchedulerTimelineView>
|
||||
<DxSchedulerWeekView ShowWorkTimeOnly="false"></DxSchedulerWeekView>
|
||||
<DxSchedulerDayView DayCount="1" ShowWorkTimeOnly="false"></DxSchedulerDayView>
|
||||
</DxScheduler>
|
||||
</div>
|
||||
</DxTabPage>
|
||||
</DxTabs>
|
||||
</div>
|
||||
</Animation>
|
||||
</div>
|
||||
@*//NE TÖRÖLD KI! - J.
|
||||
<DxTagBox TData="@(TransferStatusModel)" TValue="@(TransferStatusModel)" Data="@TransferStatusModel.AllStatuses.Values" Values="@_selectedCategories"
|
||||
@ref="_filterTag" ValuesChanged="(IEnumerable<TransferStatusModel> values) => TagBox_ValuesChanged(values)"
|
||||
ValueFieldName="StatusValue" TextFieldName="StatusName" NullText="Select status type..."
|
||||
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" aria-label="Select status type" />*@
|
||||
</div>
|
||||
</ToolbarTemplate>
|
||||
</TransferGrid>
|
||||
</div>
|
||||
</DxTabPage>
|
||||
|
||||
<div class=" col-12 col-xl-6">
|
||||
</div>
|
||||
<DxTabPage Text="Calendar">
|
||||
<div class="d-flex flex-column mb-4 pb-2">
|
||||
<DxScheduler @bind-StartDate="@StartDate"
|
||||
DataStorage="@_dataStorage"
|
||||
CssClass="w-100">
|
||||
<DxSchedulerTimelineView Duration="@TimeSpan.FromHours(48)" CellMinWidth="80">
|
||||
<Scales>
|
||||
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Day" UnitCount="1"></DxSchedulerTimeScale>
|
||||
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Hour" UnitCount="2"></DxSchedulerTimeScale>
|
||||
</Scales>
|
||||
</DxSchedulerTimelineView>
|
||||
<DxSchedulerWeekView ShowWorkTimeOnly="false"></DxSchedulerWeekView>
|
||||
<DxSchedulerDayView DayCount="1" ShowWorkTimeOnly="false"></DxSchedulerDayView>
|
||||
</DxScheduler>
|
||||
</div>
|
||||
</DxTabPage>
|
||||
</DxTabs>
|
||||
</div>
|
||||
</Animation>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class=" col-12 col-xl-6">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@code {
|
||||
private LoggerClient<ManageTransfers> _logger;
|
||||
private LoggerClient<ManageTransfers> _logger;
|
||||
|
||||
private bool _popupVisible;
|
||||
private TransferGrid _gridTransfer;
|
||||
private bool _popupVisible;
|
||||
private TransferGrid _gridTransfer;
|
||||
|
||||
private DxTagBox<TransferStatusModel, TransferStatusModel> _filterTag;
|
||||
private DxTagBox<TransferStatusModel, TransferStatusModel> _filterTag;
|
||||
|
||||
public List<string> IgnoreList =
|
||||
[
|
||||
"ReceiverEmailAddress",
|
||||
"ReceiverFullName",
|
||||
"ReceiverId",
|
||||
"SenderEmailAddress",
|
||||
"SenderFullName",
|
||||
"SenderId",
|
||||
"ContextId",
|
||||
"ContextType"
|
||||
];
|
||||
public List<string> IgnoreList =
|
||||
[
|
||||
"ReceiverEmailAddress",
|
||||
"ReceiverFullName",
|
||||
"ReceiverId",
|
||||
"SenderEmailAddress",
|
||||
"SenderFullName",
|
||||
"SenderId",
|
||||
"ContextId",
|
||||
"ContextType"
|
||||
];
|
||||
|
||||
private static List<TransferStatusModel> _selectedCategories = TransferStatusModel.AllStatuses.Values.Where(x => x.StatusValue != TransferStatusType.Finished && x.StatusValue != TransferStatusType.UserCanceled && x.StatusValue != TransferStatusType.AdminDenied).ToList();
|
||||
private string _filterText = GetFilterText(_selectedCategories.Select(x => x.StatusValue).ToList());
|
||||
private static List<TransferStatusType> _selectedCategories = Enum.GetValues<TransferStatusType>().Where(x => x != TransferStatusType.Finished && x != TransferStatusType.UserCanceled && x != TransferStatusType.AdminDenied).ToList();
|
||||
private string _filterText = GetFilterText(_selectedCategories);
|
||||
|
||||
private MessageWizardModel _messageWizardModel = new();
|
||||
// NE TÖRÖLD KI! - J.
|
||||
// private static List<TransferStatusModel> _selectedCategories = TransferStatusModel.AllStatuses.Values.Where(x => x.StatusValue != TransferStatusType.Finished && x.StatusValue != TransferStatusType.UserCanceled && x.StatusValue != TransferStatusType.AdminDenied).ToList();
|
||||
// private string _filterText = GetFilterText(_selectedCategories.Select(x => x.StatusValue).ToList());
|
||||
|
||||
public List<AppointmentModel> AppointmentModels { get; set; } = null!;
|
||||
private MessageWizardModel _messageWizardModel = new();
|
||||
|
||||
DateTime StartDate { get; set; } = DateTime.Today;
|
||||
DxSchedulerDataStorage _dataStorage = new();
|
||||
public List<AppointmentModel> AppointmentModels { get; set; } = null!;
|
||||
|
||||
DateTime StartDate { get; set; } = DateTime.Today;
|
||||
DxSchedulerDataStorage _dataStorage = new();
|
||||
|
||||
void SendMail(Transfer item)
|
||||
{
|
||||
_logger.Info($"Preparing mail to {item.ContactEmail}, {item.Id}");
|
||||
_messageWizardModel.Subject = $"[#{item.OrderId}] New message regarding your transfer";
|
||||
_messageWizardModel.ReceiverId = item.UserId;
|
||||
_messageWizardModel.ContextId = item.Id;
|
||||
_messageWizardModel.ContextType = MessageContextType.Transfer;
|
||||
_messageWizardModel.SenderId = TiamConstClient.SysAccounts["SystemEmailSender"];
|
||||
_messageWizardModel.SenderEmailAddress = TiamConstClient.SystemEmailAddress;
|
||||
_messageWizardModel.ReceiverEmailAddress = item.ContactEmail;
|
||||
_messageWizardModel.ReceiverFullName = item.FullName;
|
||||
_popupVisible = true;
|
||||
}
|
||||
|
||||
void CancelCreateClick()
|
||||
{
|
||||
|
||||
_popupVisible = false;
|
||||
}
|
||||
|
||||
void EulaPopupClosed()
|
||||
{
|
||||
//cancel clicked
|
||||
|
||||
}
|
||||
|
||||
void EulaPopupClosing(PopupClosingEventArgs args)
|
||||
{
|
||||
//myModel = new TransferWizardModel();
|
||||
_messageWizardModel = new MessageWizardModel();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
void SendMail(Transfer item)
|
||||
{
|
||||
_logger.Info($"Preparing mail to {item.ContactEmail}, {item.Id}");
|
||||
_messageWizardModel.Subject = $"[#{item.OrderId}] New message regarding your transfer";
|
||||
_messageWizardModel.ReceiverId = item.UserId;
|
||||
_messageWizardModel.ContextId = item.Id;
|
||||
_messageWizardModel.ContextType = MessageContextType.Transfer;
|
||||
_messageWizardModel.SenderId = TiamConstClient.SysAccounts["SystemEmailSender"];
|
||||
_messageWizardModel.SenderEmailAddress = TiamConstClient.SystemEmailAddress;
|
||||
_messageWizardModel.ReceiverEmailAddress = item.ContactEmail;
|
||||
_messageWizardModel.ReceiverFullName = item.FullName;
|
||||
_popupVisible = true;
|
||||
}
|
||||
public async Task SubmitForm(object result)
|
||||
{
|
||||
var messageModel = (result as MessageWizardModel)!;
|
||||
_logger.Info(messageModel.Content);
|
||||
var email = await wizardProcessor.ProcessWizardAsync<MessageWizardModel>(result.GetType(), messageModel);
|
||||
_logger.Info($"Submitted nested form: {result.GetType().FullName}");
|
||||
CancelCreateClick();
|
||||
}
|
||||
|
||||
void CancelCreateClick()
|
||||
{
|
||||
void Grid_CustomizeElement(GridCustomizeElementEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ElementType == GridElementType.HeaderCell)
|
||||
{
|
||||
e.Style = "background-color: rgba(0, 0, 0, 0.08)";
|
||||
e.CssClass = "header-bold";
|
||||
}
|
||||
|
||||
_popupVisible = false;
|
||||
}
|
||||
if (e.ElementType != GridElementType.DataRow) return;
|
||||
|
||||
void EulaPopupClosed()
|
||||
{
|
||||
//cancel clicked
|
||||
var transferStatus = e.Grid?.GetRowValue(e.VisibleIndex, "TransferStatusType");
|
||||
if (transferStatus == null) return;
|
||||
|
||||
}
|
||||
var transferStatusByte = (byte)transferStatus;
|
||||
|
||||
void EulaPopupClosing(PopupClosingEventArgs args)
|
||||
{
|
||||
//myModel = new TransferWizardModel();
|
||||
_messageWizardModel = new MessageWizardModel();
|
||||
}
|
||||
switch (transferStatusByte)
|
||||
{
|
||||
case 5:
|
||||
e.CssClass = "bg-important";
|
||||
break;
|
||||
case > 5 and < 35:
|
||||
e.CssClass = "bg-attention";
|
||||
break;
|
||||
case 35:
|
||||
e.CssClass = "bg-finished";
|
||||
break;
|
||||
case > 35:
|
||||
e.CssClass = "bg-cancel";
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Grid_CustomizeElement; {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
void Grid_CustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||
{
|
||||
if (!e.IsNew) return;
|
||||
|
||||
var transferEditModel = (Transfer)e.EditModel; //TODO not valid cast
|
||||
transferEditModel.Id = Guid.NewGuid();
|
||||
transferEditModel.ToAddress = "Where to?";
|
||||
transferEditModel.FromAddress = "From where?";
|
||||
transferEditModel.Appointment = DateTime.UtcNow.AddDays(3);
|
||||
transferEditModel.PassengerCount = 1;
|
||||
transferEditModel.FirstName = "John";
|
||||
transferEditModel.LastName = "Doe";
|
||||
transferEditModel.ContactPhone = "+00000000000";
|
||||
transferEditModel.ContactEmail = "your@email.address";
|
||||
}
|
||||
|
||||
private static string GetFilterText(ICollection<TransferStatusType> selectedTransferStatuses)
|
||||
=> selectedTransferStatuses.Count == 0 ? string.Empty : CriteriaOperator.FromLambda<Transfer>(t => selectedTransferStatuses.Contains(t.TransferStatusType)).ToString();
|
||||
|
||||
void TagBox_ValuesChanged(IEnumerable<TransferStatusType> newSelectedCategories)
|
||||
{
|
||||
var filterText = string.Empty;
|
||||
InOperator? filterCriteria = null;
|
||||
|
||||
_selectedCategories = newSelectedCategories.ToList();
|
||||
|
||||
if (_selectedCategories.Count > 0)
|
||||
{
|
||||
filterCriteria = new InOperator(nameof(Transfer.TransferStatusType), _selectedCategories);
|
||||
filterText = GetFilterText(_selectedCategories);
|
||||
}
|
||||
|
||||
_filterText = filterText;
|
||||
_gridTransfer.SetFieldFilterCriteria(nameof(Transfer.TransferStatusType), filterCriteria);
|
||||
}
|
||||
|
||||
// NE TÖRÖLD KI! - J.
|
||||
// void TagBox_ValuesChanged(IEnumerable<TransferStatusModel> newSelectedCategories)
|
||||
// {
|
||||
// var filterText = string.Empty;
|
||||
// InOperator? filterCriteria = null;
|
||||
|
||||
// _selectedCategories = newSelectedCategories.ToList();
|
||||
// //_selectedCategories.Clear();
|
||||
// //_selectedCategories.AddRange(newSelectedCategories);
|
||||
|
||||
// if (_selectedCategories.Count > 0)
|
||||
// {
|
||||
// filterCriteria = new InOperator(nameof(Transfer.TransferStatusType), _selectedCategories.Select(c => c.StatusValue));
|
||||
// filterText = GetFilterText(_selectedCategories.Select(x => (TransferStatusType)x.StatusValue).ToList());
|
||||
// }
|
||||
|
||||
// _filterText = filterText;
|
||||
// _gridTransfer.SetFieldFilterCriteria(nameof(Transfer.TransferStatusType), filterCriteria);
|
||||
// }
|
||||
|
||||
private void DataSourceChanged(IList<Transfer> transfers)
|
||||
{
|
||||
_logger.Info("DataSourceChanged called");
|
||||
|
||||
InitializeAppointments(transfers);
|
||||
|
||||
if (_selectedCategories.Count > 0)
|
||||
TagBox_ValuesChanged(_selectedCategories);
|
||||
|
||||
// if(!SelectedCategories.Any())
|
||||
// SelectedCategories = [Statuses.FirstOrDefault(x => x.StatusValue == (byte)TransferStatusType.Finished)!];
|
||||
|
||||
// var filterTransferStatusType = Statuses.FirstOrDefault(x => x.StatusValue == (byte)TransferStatusType.Finished)!;
|
||||
|
||||
// if (SelectedCategories.All(x => x.StatusValue != filterTransferStatusType.StatusValue))
|
||||
// SelectedCategories.Add(filterTransferStatusType);
|
||||
}
|
||||
|
||||
private void DataSourceItemChanging(GridDataItemChangingEventArgs<Transfer> args)
|
||||
{
|
||||
_logger.Info("DataSourceItemChanging called");
|
||||
}
|
||||
|
||||
private void DataSourceItemChanged(GridDataItemChangedEventArgs<Transfer> args)
|
||||
{
|
||||
_logger.Info("DataSourceItemChanged called");
|
||||
|
||||
AppointmentModels.UpdateCollection(CreateAppointmentModel(args.DataItem), args.TrackingState == TrackingState.Remove);
|
||||
}
|
||||
|
||||
private void DataItemSaving(GridEditModelSavingEventArgs e)
|
||||
{
|
||||
_logger.Info("DataItemSaving called");
|
||||
}
|
||||
|
||||
private void DataItemDeleting(GridDataItemDeletingEventArgs e)
|
||||
{
|
||||
_logger.Info($"DataItemDeleting OnItemDeleting");
|
||||
}
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
_logger = new LoggerClient<ManageTransfers>(_logWriters.ToArray());
|
||||
|
||||
//await AdminSignalRClient.GetAllCarsByProductIdAsync(TiamConstClient.TransferProductId, _cars, StateHasChanged);
|
||||
|
||||
//await base.OnInitializedAsync();
|
||||
return base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void InitializeAppointments(ICollection<Transfer> transferDataList)
|
||||
{
|
||||
_logger.Info("InitializeAppointments called");
|
||||
|
||||
AppointmentModels = new List<AppointmentModel>(transferDataList.Count);
|
||||
|
||||
foreach (var transfer in transferDataList)
|
||||
{
|
||||
// var bnm = DataStorage.CreateAppointmentItem();
|
||||
// bnm.Start = transfer.Appointment;
|
||||
// bnm.Description = $"{transfer.FullName}, {transfer.ToAddress}";
|
||||
// bnm.Location = transfer.FromAddress;
|
||||
// bnm.Subject = "Simple transfer";
|
||||
|
||||
AppointmentModels.Add(CreateAppointmentModel(transfer));
|
||||
}
|
||||
|
||||
_dataStorage = new DxSchedulerDataStorage
|
||||
{
|
||||
AppointmentMappings = new DxSchedulerAppointmentMappings()
|
||||
{
|
||||
Type = "AppointmentType",
|
||||
Start = "StartDate",
|
||||
End = "EndDate",
|
||||
Subject = "Caption",
|
||||
AllDay = "AllDay",
|
||||
Location = "Location",
|
||||
Description = "Description",
|
||||
LabelId = "Label",
|
||||
StatusId = "Status",
|
||||
RecurrenceInfo = "Recurrence"
|
||||
},
|
||||
|
||||
AppointmentsSource = AppointmentModels
|
||||
};
|
||||
}
|
||||
|
||||
public AppointmentModel CreateAppointmentModel(Transfer transfer)
|
||||
{
|
||||
return new AppointmentModel { Id = transfer.Id, StartDate = transfer.Appointment, EndDate = transfer.Appointment.AddMinutes(30), Description = $"{transfer.FullName}, {transfer.ToAddress}", Location = transfer.FromAddress, Caption = "Simple transfer" };
|
||||
}
|
||||
|
||||
void ColumnChooserButton_Click()
|
||||
{
|
||||
_gridTransfer.ShowColumnChooser();
|
||||
}
|
||||
|
||||
|
||||
public async Task SubmitForm(object result)
|
||||
{
|
||||
var messageModel = (result as MessageWizardModel)!;
|
||||
_logger.Info(messageModel.Content);
|
||||
var email = await wizardProcessor.ProcessWizardAsync<MessageWizardModel>(result.GetType(), messageModel);
|
||||
_logger.Info($"Submitted nested form: {result.GetType().FullName}");
|
||||
CancelCreateClick();
|
||||
}
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
//_gridTransfer.ExpandDetailRow(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Grid_CustomizeElement(GridCustomizeElementEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ElementType == GridElementType.HeaderCell)
|
||||
{
|
||||
e.Style = "background-color: rgba(0, 0, 0, 0.08)";
|
||||
e.CssClass = "header-bold";
|
||||
}
|
||||
private void OnSelectedDataItemChanged(object selectedRow)
|
||||
{
|
||||
if (selectedRow is not Transfer selectedTransfer) return;
|
||||
|
||||
if (e.ElementType != GridElementType.DataRow) return;
|
||||
RefreshTransferToDriversData(selectedTransfer, () => { _gridTransfer.Reload(); });
|
||||
}
|
||||
|
||||
var transferStatus = e.Grid?.GetRowValue(e.VisibleIndex, "TransferStatusType");
|
||||
if (transferStatus == null) return;
|
||||
private void RefreshTransferToDriversData(Transfer? transfer, Action? callback = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (transfer == null || transfer.TransferToDrivers.Count != 0 || transfer.TransferStatusType < TransferStatusType.AssignedToDriver)
|
||||
return;
|
||||
|
||||
var transferStatusByte = (byte)transferStatus;
|
||||
AdminSignalRClient.GetByIdAsync<List<TransferToDriver>?>(SignalRTags.GetTransferDriversByTransferId, x =>
|
||||
{
|
||||
if (x?.ResponseData == null) return Task.CompletedTask;
|
||||
|
||||
switch (transferStatusByte)
|
||||
{
|
||||
case 5:
|
||||
e.CssClass = "bg-important";
|
||||
break;
|
||||
case > 5 and < 35:
|
||||
e.CssClass = "bg-attention";
|
||||
break;
|
||||
case 35:
|
||||
e.CssClass = "bg-finished";
|
||||
break;
|
||||
case > 35:
|
||||
e.CssClass = "bg-cancel";
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Grid_CustomizeElement; {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
transfer.TransferToDrivers.UpdateCollection<TransferToDriver>(x.ResponseData, false);
|
||||
callback?.Invoke();
|
||||
|
||||
void Grid_CustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||
{
|
||||
if (!e.IsNew) return;
|
||||
|
||||
var transferEditModel = (Transfer)e.EditModel; //TODO not valid cast
|
||||
transferEditModel.Id = Guid.NewGuid();
|
||||
transferEditModel.ToAddress = "Where to?";
|
||||
transferEditModel.FromAddress = "From where?";
|
||||
transferEditModel.Appointment = DateTime.UtcNow.AddDays(3);
|
||||
transferEditModel.PassengerCount = 1;
|
||||
transferEditModel.FirstName = "John";
|
||||
transferEditModel.LastName = "Doe";
|
||||
transferEditModel.ContactPhone = "+00000000000";
|
||||
transferEditModel.ContactEmail = "your@email.address";
|
||||
}
|
||||
|
||||
private static string GetFilterText(ICollection<TransferStatusType> selectedTransferStatuses)
|
||||
=> selectedTransferStatuses.Count == 0 ? string.Empty : CriteriaOperator.FromLambda<Transfer>(t => selectedTransferStatuses.Contains(t.TransferStatusType)).ToString();
|
||||
|
||||
void TagBox_ValuesChanged(IEnumerable<TransferStatusModel> newSelectedCategories)
|
||||
{
|
||||
var filterText = string.Empty;
|
||||
InOperator? filterCriteria = null;
|
||||
|
||||
_selectedCategories = newSelectedCategories.ToList();
|
||||
|
||||
if (_selectedCategories.Count > 0)
|
||||
{
|
||||
filterCriteria = new InOperator("TransferStatusType", _selectedCategories.Select(c => c.StatusValue));
|
||||
filterText = GetFilterText(_selectedCategories.Select(x => (TransferStatusType)x.StatusValue).ToList());
|
||||
}
|
||||
|
||||
_filterText = filterText;
|
||||
_gridTransfer.SetFieldFilterCriteria("TransferStatusType", filterCriteria);
|
||||
}
|
||||
|
||||
private void DataSourceChanged(IList<Transfer> transfers)
|
||||
{
|
||||
_logger.Info("DataSourceChanged called");
|
||||
|
||||
InitializeAppointments(transfers);
|
||||
|
||||
if (_selectedCategories.Count > 0)
|
||||
TagBox_ValuesChanged(_selectedCategories);
|
||||
|
||||
// if(!SelectedCategories.Any())
|
||||
// SelectedCategories = [Statuses.FirstOrDefault(x => x.StatusValue == (byte)TransferStatusType.Finished)!];
|
||||
|
||||
// var filterTransferStatusType = Statuses.FirstOrDefault(x => x.StatusValue == (byte)TransferStatusType.Finished)!;
|
||||
|
||||
// if (SelectedCategories.All(x => x.StatusValue != filterTransferStatusType.StatusValue))
|
||||
// SelectedCategories.Add(filterTransferStatusType);
|
||||
}
|
||||
|
||||
private void DataSourceItemChanging(GridDataItemChangingEventArgs<Transfer> args)
|
||||
{
|
||||
_logger.Info("DataSourceItemChanging called");
|
||||
}
|
||||
|
||||
private void DataSourceItemChanged(GridDataItemChangedEventArgs<Transfer> args)
|
||||
{
|
||||
_logger.Info("DataSourceItemChanged called");
|
||||
|
||||
AppointmentModels.UpdateCollection(CreateAppointmentModel(args.DataItem), args.TrackingState == TrackingState.Remove);
|
||||
}
|
||||
|
||||
private void DataItemSaving(GridEditModelSavingEventArgs e)
|
||||
{
|
||||
_logger.Info("DataItemSaving called");
|
||||
}
|
||||
|
||||
private void DataItemDeleting(GridDataItemDeletingEventArgs e)
|
||||
{
|
||||
_logger.Info($"DataItemDeleting OnItemDeleting");
|
||||
}
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
_logger = new LoggerClient<ManageTransfers>(_logWriters.ToArray());
|
||||
|
||||
return base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void InitializeAppointments(ICollection<Transfer> transferDataList)
|
||||
{
|
||||
_logger.Info("InitializeAppointments called");
|
||||
|
||||
AppointmentModels = new List<AppointmentModel>(transferDataList.Count);
|
||||
|
||||
foreach (var transfer in transferDataList)
|
||||
{
|
||||
// var bnm = DataStorage.CreateAppointmentItem();
|
||||
// bnm.Start = transfer.Appointment;
|
||||
// bnm.Description = $"{transfer.FullName}, {transfer.ToAddress}";
|
||||
// bnm.Location = transfer.FromAddress;
|
||||
// bnm.Subject = "Simple transfer";
|
||||
|
||||
AppointmentModels.Add(CreateAppointmentModel(transfer));
|
||||
}
|
||||
|
||||
_dataStorage = new DxSchedulerDataStorage
|
||||
{
|
||||
AppointmentMappings = new DxSchedulerAppointmentMappings()
|
||||
{
|
||||
Type = "AppointmentType",
|
||||
Start = "StartDate",
|
||||
End = "EndDate",
|
||||
Subject = "Caption",
|
||||
AllDay = "AllDay",
|
||||
Location = "Location",
|
||||
Description = "Description",
|
||||
LabelId = "Label",
|
||||
StatusId = "Status",
|
||||
RecurrenceInfo = "Recurrence"
|
||||
},
|
||||
|
||||
AppointmentsSource = AppointmentModels
|
||||
};
|
||||
}
|
||||
|
||||
public AppointmentModel CreateAppointmentModel(Transfer transfer)
|
||||
{
|
||||
return new AppointmentModel { Id = transfer.Id, StartDate = transfer.Appointment, EndDate = transfer.Appointment.AddMinutes(30), Description = $"{transfer.FullName}, {transfer.ToAddress}", Location = transfer.FromAddress, Caption = "Simple transfer" };
|
||||
}
|
||||
|
||||
void ColumnChooserButton_Click()
|
||||
{
|
||||
_gridTransfer.ShowColumnChooser();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
//_gridTransfer.ExpandDetailRow(0);
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}, transfer.Id).Forget();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"RefreshTransferToDriversData error; transferId: {transfer?.Id}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,14 +27,15 @@
|
|||
@inject AdminSignalRClient AdminSignalRClient;
|
||||
@inject ISessionServiceClient sessionService
|
||||
@inject IComponentUpdateService ComponentUpdateService
|
||||
@inject ITransferDataService transferDataService
|
||||
|
||||
<MessageDetailGrid CssClass="my-grid" @ref="_messageGrid"
|
||||
Logger="_logger"
|
||||
SignalRClient="AdminSignalRClient"
|
||||
GetAllMessageTag="GetAllMessageTag"
|
||||
ContextIds="@(ContextId.IsNullOrEmpty() ? throw new InvalidDataException($"ContextId.IsNullOrEmpty(); ContextId: {ContextId}") : [ContextId.Value])"
|
||||
CustomizeElement="CustomizeElement"
|
||||
ShowFilterRow="ShowFilterRow">
|
||||
Logger="_logger"
|
||||
SignalRClient="AdminSignalRClient"
|
||||
GetAllMessageTag="GetAllMessageTag"
|
||||
ContextIds="@(ContextId.IsNullOrEmpty() ? throw new InvalidDataException($"ContextId.IsNullOrEmpty(); ContextId: {ContextId}") : [ContextId.Value])"
|
||||
CustomizeElement="CustomizeElement"
|
||||
ShowFilterRow="ShowFilterRow">
|
||||
<Columns>
|
||||
<DxGridCommandColumn Width="135" MinWidth="135" Visible="AcDomain.IsDeveloperVersion" DeleteButtonVisible="AcDomain.IsDeveloperVersion" EditButtonVisible="AcDomain.IsDeveloperVersion" FixedPosition="GridColumnFixedPosition.Left" />
|
||||
<DxGridDataColumn FieldName="SenderId" Caption=" " Width="30px" ShowInColumnChooser="AcDomain.IsDeveloperVersion" DisplayFormat="N" AllowSort="false">
|
||||
|
|
@ -163,10 +164,24 @@
|
|||
|
||||
private Guid? myUserId;
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_logger = new LoggerClient<MessageDetailGridComponent>(LogWriters.ToArray());
|
||||
myUserId = _sessionService.User.UserId;
|
||||
if(sessionService.User != null)
|
||||
{
|
||||
myUserId = _sessionService.User.UserId;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ContextId != null)
|
||||
{
|
||||
//should be transfer because in any other way, the user must be logged in
|
||||
myUserId = Guid.Empty; //TODO get userId by transfer
|
||||
var transfer = await AdminSignalRClient.GetTransferById((Guid)ContextId);
|
||||
myUserId = transfer.UserId;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void CustomizeElement(GridCustomizeElementEventArgs e)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
@page "/sysadmin/manage-tours"
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using TIAM.Entities.Transfers
|
||||
@using TIAMWebApp.Shared.Application.Interfaces
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@using TIAMSharedUI.Shared
|
||||
@inject ITransferDataService TransferDataService
|
||||
@inject TourService TourService
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
@layout AdminLayout
|
||||
|
||||
<PageTitle>Manage Tours</PageTitle>
|
||||
|
||||
<h1 class="text-center m-4">Manage Tours</h1>
|
||||
|
||||
<div class="container">
|
||||
<div class="mb-4">
|
||||
<h4>Create New Tour</h4>
|
||||
|
||||
<EditForm Model="@newTour" OnValidSubmit="HandleSubmit">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Select Transfer Destination</label>
|
||||
<InputSelect @bind-Value="newTour.TransferDestinationId" class="form-control">
|
||||
<option value="">-- Select --</option>
|
||||
@foreach (var dest in TransferDestinations)
|
||||
{
|
||||
<option value="@dest.Id">@dest.Name (@dest.AddressString)</option>
|
||||
}
|
||||
</InputSelect>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Tour name</label>
|
||||
<InputTextArea @bind-Value="newTour.Name" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Description</label>
|
||||
<InputTextArea @bind-Value="newTour.Description" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Cover Photo</label>
|
||||
<InputFile OnChange="HandleFileChange" />
|
||||
@if (!string.IsNullOrEmpty(UploadStatus))
|
||||
{
|
||||
<div class="text-muted mt-1">@UploadStatus</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary me-2" type="submit">
|
||||
@(IsEditing ? "Update Tour" : "Save Tour")
|
||||
</button>
|
||||
@if (IsEditing)
|
||||
{
|
||||
<button class="btn btn-secondary" type="button" @onclick="CancelEdit">Cancel</button>
|
||||
}
|
||||
</EditForm>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div>
|
||||
<h4>Existing Tours</h4>
|
||||
@if (Tours.Any())
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var tour in Tours)
|
||||
{
|
||||
var dest = TransferDestinations.FirstOrDefault(d => d.Id == tour.TransferDestinationId);
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<img src="@tour.CoverImageUrl" style="max-height: 100px;"/>
|
||||
<span>
|
||||
<strong>@tour?.Title</strong> — @tour.FancyDescription
|
||||
</span>
|
||||
<button class="btn btn-sm btn-secondary me-2" @onclick="() => EditTour(tour)">Edit</button>
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DeleteTourAsync(tour.Id)">Delete</button>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>No tours available.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<TransferDestination> TransferDestinations = [];
|
||||
private List<TourInfo> Tours = [];
|
||||
|
||||
private TourFormModel newTour = new();
|
||||
private IBrowserFile? uploadedFile;
|
||||
private string UploadStatus = string.Empty;
|
||||
|
||||
private bool IsEditing = false;
|
||||
private Guid? EditingTourId = null;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
TransferDestinations = (await TransferDataService.GetDestinationsAsync()).ToList();
|
||||
Tours = (await TourService.GetAllAsync()).ToList();
|
||||
}
|
||||
|
||||
private void EditTour(TourInfo tour)
|
||||
{
|
||||
newTour = new TourFormModel
|
||||
{
|
||||
TransferDestinationId = tour.TransferDestinationId,
|
||||
Name = tour.Title,
|
||||
Description = tour.FancyDescription,
|
||||
ImageBytes = null,
|
||||
ImageFileName = null
|
||||
};
|
||||
|
||||
IsEditing = true;
|
||||
EditingTourId = tour.Id;
|
||||
UploadStatus = string.Empty;
|
||||
}
|
||||
|
||||
private void CancelEdit()
|
||||
{
|
||||
newTour = new TourFormModel();
|
||||
uploadedFile = null;
|
||||
IsEditing = false;
|
||||
EditingTourId = null;
|
||||
UploadStatus = string.Empty;
|
||||
}
|
||||
|
||||
// private async Task SaveTourAsync()
|
||||
// {
|
||||
// if (uploadedFile is not null)
|
||||
// {
|
||||
// using var stream = uploadedFile.OpenReadStream(maxAllowedSize: 5 * 1024 * 1024);
|
||||
// using var ms = new MemoryStream();
|
||||
// await stream.CopyToAsync(ms);
|
||||
// newTour.ImageBytes = ms.ToArray();
|
||||
// newTour.ImageFileName = uploadedFile.Name;
|
||||
// }
|
||||
|
||||
// TourInfo tourToCreate = new TourInfo();
|
||||
// tourToCreate.TransferDestinationId = newTour.TransferDestinationId;
|
||||
// tourToCreate.FancyDescription = newTour.Description;
|
||||
// tourToCreate.Title = newTour.Name;
|
||||
// tourToCreate.CoverImageUrl = "";
|
||||
// if (tourToCreate.TransferDestinationId == Guid.Empty)
|
||||
// {
|
||||
// throw new InvalidOperationException("Transfer Destination must be selected.");
|
||||
// }
|
||||
|
||||
// await TourService.CreateAsync(tourToCreate, uploadedFile);
|
||||
// newTour = new();
|
||||
// uploadedFile = null;
|
||||
// UploadStatus = string.Empty;
|
||||
// Tours = (await TourService.GetAllAsync()).ToList();
|
||||
// }
|
||||
|
||||
private async Task HandleSubmit()
|
||||
{
|
||||
if (uploadedFile is not null)
|
||||
{
|
||||
using var stream = uploadedFile.OpenReadStream(maxAllowedSize: 5 * 1024 * 1024);
|
||||
using var ms = new MemoryStream();
|
||||
await stream.CopyToAsync(ms);
|
||||
newTour.ImageBytes = ms.ToArray();
|
||||
newTour.ImageFileName = uploadedFile.Name;
|
||||
}
|
||||
|
||||
if (IsEditing && EditingTourId.HasValue)
|
||||
{
|
||||
var updatedTour = new TourInfo
|
||||
{
|
||||
Id = EditingTourId.Value,
|
||||
TransferDestinationId = newTour.TransferDestinationId,
|
||||
Title = newTour.Name,
|
||||
FancyDescription = newTour.Description,
|
||||
CoverImageUrl = "" // assume your service handles image URL logic
|
||||
};
|
||||
|
||||
await TourService.UpdateAsync(updatedTour, uploadedFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tourToCreate = new TourInfo
|
||||
{
|
||||
TransferDestinationId = newTour.TransferDestinationId,
|
||||
Title = newTour.Name,
|
||||
FancyDescription = newTour.Description,
|
||||
CoverImageUrl = newTour.ImageFileName
|
||||
};
|
||||
|
||||
await TourService.CreateAsync(tourToCreate, uploadedFile);
|
||||
}
|
||||
|
||||
// Reset form
|
||||
newTour = new TourFormModel();
|
||||
uploadedFile = null;
|
||||
IsEditing = false;
|
||||
EditingTourId = null;
|
||||
UploadStatus = string.Empty;
|
||||
|
||||
Tours = (await TourService.GetAllAsync()).ToList();
|
||||
}
|
||||
|
||||
private void HandleFileChange(InputFileChangeEventArgs e)
|
||||
{
|
||||
uploadedFile = e.File;
|
||||
UploadStatus = $"Selected: {uploadedFile.Name}";
|
||||
}
|
||||
|
||||
private async Task DeleteTourAsync(Guid id)
|
||||
{
|
||||
await TourService.DeleteAsync(id);
|
||||
Tours = (await TourService.GetAllAsync()).ToList();
|
||||
}
|
||||
|
||||
public class TourFormModel
|
||||
{
|
||||
[Required]
|
||||
public Guid TransferDestinationId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "Tour name cannot exceed 100 characters.")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public byte[]? ImageBytes { get; set; }
|
||||
public string? ImageFileName { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
newDestination.Id = Guid.NewGuid();
|
||||
newDestination.Name = "Destination name";
|
||||
newDestination.Description = "Type some description here";
|
||||
newDestination.AddressString = "The address of the destination";
|
||||
newDestination.AddressString = $"The address of: {newDestination.Name}";
|
||||
Guid addressId = Guid.NewGuid();
|
||||
newDestination.Address = new Address();
|
||||
newDestination.Address.Id = addressId;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<div class="page">
|
||||
<TiamErrorBoundaryComponent LoggerCategory="AdminLayout" OnError="HandleError">
|
||||
|
||||
<AppLaunchComponent />
|
||||
<AdminNavMenu />
|
||||
<NavHelperComponent />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<!-- footer -->
|
||||
<footer class="pt-lg-10 pt-5 footer bg-white">
|
||||
<footer class="pt-lg-10 pt-5 footer bg-light">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-6 col-12">
|
||||
<!-- about company -->
|
||||
<div class="mb-4">
|
||||
<img src="../assets/images/brand/logo/logo.svg" alt="" class="logo-inverse ">
|
||||
<img src="_content/TIAMSharedUI/images/logo_wide.png" alt="" class="logo-inverse ">
|
||||
<div class="mt-4">
|
||||
<p>
|
||||
Geek is feature-rich components and beautifully Bootstrap UIKit for developers, built with bootstrap
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ namespace TIAMSharedUI.Shared.Components.Grids;
|
|||
|
||||
public class TransferGrid : TiamGrid<Transfer>
|
||||
{
|
||||
|
||||
|
||||
public TransferGrid() : base()
|
||||
{
|
||||
GetAllMessageTag = SignalRTags.GetTransfersByFilterText;//SignalRTags.GetTransfers;
|
||||
|
|
|
|||
|
|
@ -23,9 +23,38 @@
|
|||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="explore-the-region">
|
||||
@localizer.GetString("NavMenu.ExploreTheRegion")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="signature-ride-packages">
|
||||
@localizer.GetString("NavMenu.SignatureRidePackages")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="how-it-works">
|
||||
@localizer.GetString("NavMenu.HowItWorks")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="about">
|
||||
@localizer.GetString("NavMenu.About")
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="contact">
|
||||
@localizer.GetString("NavMenu.Contact")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="transfer">
|
||||
@localizer.GetString("NavMenu.Transfer")
|
||||
@localizer.GetString("NavMenu.BookNow")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
|
|
@ -50,17 +79,12 @@
|
|||
|
||||
|
||||
|
||||
<li class="nav-item">
|
||||
<NavLink class="nav-link" href="about">
|
||||
@localizer.GetString("NavMenu.About")
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
|
||||
@* <li class="nav-item">
|
||||
<NavLink class="nav-link" href="roadmap">
|
||||
@localizer.GetString("NavMenu.Roadmap")
|
||||
</NavLink>
|
||||
</li>
|
||||
</li> *@
|
||||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
.navbar {
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
backdrop-filter: blur(8px);
|
||||
background-color: rgba(255, 255, 255, 0.7)
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Services
|
||||
@inject TourService TourService
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<div class="container">
|
||||
<section class="game-section" style="max-width: 100%; overflow-x:hidden">
|
||||
<div class="text-center">
|
||||
<h1>Tours</h1>
|
||||
<h2>Please select!</h2>
|
||||
</div>
|
||||
<div class="owl-carousel custom-carousel owl-theme">
|
||||
@if (Tours != null && Tours.Any()) // Only render the loop if Tours has data
|
||||
{
|
||||
foreach (var item in Tours)
|
||||
{
|
||||
<div class="item" style="background-image: url(@item.CoverImageUrl);">
|
||||
<div class="item-desc" style="height: 100%; background-color: rgba(0,0,0,0.3);">
|
||||
<p style="padding-top:70px">@item.Created</p>
|
||||
<p>@item.FancyDescription</p>
|
||||
@* <p>@item.TransferDestinationId</p> *@
|
||||
<div>
|
||||
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 1))">1-3 passengers</button>
|
||||
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 2))">4-6 passengers</button>
|
||||
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 3))">7-8 passengers</button>
|
||||
</div>
|
||||
<div class="glass" style="position: absolute; top:0px; left:0px; padding:10px; width:100%">
|
||||
<h4>@item.Title</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Loading tours...</p>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function initializeOwlCarousel() {
|
||||
console.log("Initializing Owl Carousel..."); // For debugging
|
||||
$(".custom-carousel").owlCarousel({
|
||||
autoWidth: true,
|
||||
loop: true
|
||||
});
|
||||
// Ensure this runs only once per initialization
|
||||
$(document).ready(function () { // This ready might not be needed if called after DOM update
|
||||
$(".custom-carousel .item").off("click").on("click", function () { // Use .off().on() to prevent multiple handlers
|
||||
$(".custom-carousel .item").not($(this)).removeClass("active");
|
||||
$(this).toggleClass("active");
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@code {
|
||||
public List<TourInfo> Tours = new List<TourInfo>();
|
||||
private bool _owlCarouselInitialized = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Tours = (await TourService.GetAllAsync()).ToList();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
// Only initialize Owl Carousel once, after data is loaded and rendered
|
||||
if (Tours != null && Tours.Any() && !_owlCarouselInitialized)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("initializeOwlCarousel");
|
||||
_owlCarouselInitialized = true; // Set flag to true after successful initialization
|
||||
}
|
||||
}
|
||||
|
||||
private void Book(Guid id, int category)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/book-a-tour/{id.ToString()}/{category}");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
|
||||
|
||||
/******* Common Element CSS Start ******/
|
||||
|
||||
|
||||
body {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
outline: none;
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
a:active,
|
||||
a:visited,
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #e73700;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 48px;
|
||||
padding-bottom: 16px;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
font-weight: 700;
|
||||
position: relative;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
button {
|
||||
outline: none !important;
|
||||
}
|
||||
/******* Common Element CSS End *********/
|
||||
|
||||
/* -------- title style ------- */
|
||||
.line-title {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.line-title::before,
|
||||
.line-title::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.line-title::before {
|
||||
width: 100%;
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.line-title::after {
|
||||
width: 32px;
|
||||
background: #e73700;
|
||||
}
|
||||
|
||||
/******* Middle section CSS Start ******/
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 5px 50px;*/
|
||||
}
|
||||
|
||||
.game-section .owl-stage {
|
||||
margin: 15px 0;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 15px 60px;
|
||||
width: 320px;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
align-items: flex-end;
|
||||
-webkit-align-items: flex-end;
|
||||
background: #343434 no-repeat center center / cover;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 500px;
|
||||
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
-webkit-box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
}
|
||||
|
||||
.game-section .item:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
padding: 0 24px 12px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
transform: translateY(calc(100% - 54px));
|
||||
-webkit-transform: translateY(calc(100% - 54px));
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
.game-section .item.active .item-desc {
|
||||
transform: none;
|
||||
-webkit-transform: none;
|
||||
}
|
||||
|
||||
.game-section .item-desc p {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(32px);
|
||||
transform: translateY(32px);
|
||||
transition: all 0.4s ease-in-out 0.2s;
|
||||
-webkit-transition: all 0.4s ease-in-out 0.2s;
|
||||
}
|
||||
|
||||
.game-section .item.active .item-desc p {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.game-section .owl-theme.custom-carousel .owl-dots {
|
||||
margin-top: -20px;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
/******** Middle section CSS End *******/
|
||||
|
||||
/***** responsive css Start ******/
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1199px) {
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 50px 5px;*/
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 12px 60px;
|
||||
width: 260px;
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
transform: translateY(calc(100% - 46px));
|
||||
-webkit-transform: translateY(calc(100% - 46px));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.line-title {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 50px 5px 40px;*/
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 12px 60px;
|
||||
width: 240px;
|
||||
height: 330px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
transform: translateY(calc(100% - 42px));
|
||||
-webkit-transform: translateY(calc(100% - 42px));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 19px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.line-title {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
padding: 30px 15px 20px;
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 10px 40px;
|
||||
width: 200px;
|
||||
height: 280px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 270px;
|
||||
box-shadow: 6px 10px 10px rgba(0, 0, 0, 0.25);
|
||||
-webkit-box-shadow: 6px 10px 10px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
padding: 0 14px 5px;
|
||||
transform: translateY(calc(100% - 42px));
|
||||
-webkit-transform: translateY(calc(100% - 42px));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,24 @@
|
|||
@using BlazorAnimation
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide.UI
|
||||
<header style="padding-bottom: @PBottom;">
|
||||
<header style="padding-bottom: @PBottom;" class="bg-light">
|
||||
|
||||
<div id="owl-demo" class="owl-carousel owl-theme" style="/* position:absolute; */ z-index: 1;">
|
||||
|
||||
@{
|
||||
foreach (var slider in SliderItems)
|
||||
{
|
||||
<div class="item d-flex align-items-center" style="height: @Height;">
|
||||
<img src="@slider.ImageUrl" class="my-auto" alt="@slider.Title">
|
||||
<div class="item d-flex align-items-center" style="height: @Height; background-image : url('@slider.ImageUrl'); background-size:cover; background-position:center; background-color: rgba(0, 0, 0, 0.6); background-blend-mode: overlay;">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-6 col-sm-12 text-white">
|
||||
<h1>@slider.Title</h1>
|
||||
<p>@slider.Subtitle</p>
|
||||
<a href="@slider.ButtonUrl" class="btn btn-primary">@slider.ButtonText</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<NavMenu />
|
||||
</div-->
|
||||
|
||||
@* <main class="bg-gradient"> *@
|
||||
<main>
|
||||
<article class="content">
|
||||
<CascadingValue Value=PopupMessageBox>
|
||||
|
|
|
|||
|
|
@ -12,13 +12,14 @@
|
|||
@inject NavigationManager NavigationManager
|
||||
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
|
||||
@inject IJSRuntime jsRuntime
|
||||
@inject IComponentUpdateService componentUpdateService
|
||||
|
||||
|
||||
<div class="w-100" style="height:40px; position:fixed; z-index: 10000;">
|
||||
<DxMenu CssClass="my-menu" SizeMode="SizeMode.Medium" Title="Tour I Am" ItemsPosition="ItemPosition.End" CollapseItemsToHamburgerMenu="true"
|
||||
Orientation="Orientation"
|
||||
DisplayMode="DisplayMode"
|
||||
HamburgerButtonPosition="MenuHamburgerButtonPosition.Right">
|
||||
Orientation="Orientation"
|
||||
DisplayMode="DisplayMode"
|
||||
HamburgerButtonPosition="MenuHamburgerButtonPosition.Right">
|
||||
<TitleTemplate>
|
||||
@{
|
||||
if (_isMobile)
|
||||
|
|
@ -32,29 +33,29 @@
|
|||
@if (IsSysAdmin)
|
||||
{
|
||||
<DxToolbarItem Name="Transfers"
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-face-smile"
|
||||
Tooltip="Transfers"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url1)" />
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-face-smile"
|
||||
Tooltip="Transfers"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url1)" />
|
||||
|
||||
}
|
||||
@if (IsDriver)
|
||||
{
|
||||
<DxToolbarItem Name="Transfers"
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-taxi"
|
||||
Tooltip="My tasks"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url2)" />
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-taxi"
|
||||
Tooltip="My tasks"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url2)" />
|
||||
|
||||
}
|
||||
<DxToolbarItem Name="Messages"
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-envelope"
|
||||
Tooltip="Messages"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url3)" />
|
||||
BeginGroup="true"
|
||||
IconCssClass="fa-solid fa-envelope"
|
||||
Tooltip="Messages"
|
||||
Alignment="ToolbarItemAlignment.Right"
|
||||
Click="() => NavigationManager.NavigateTo(url3)" />
|
||||
</Items>
|
||||
</DxToolbar>
|
||||
}
|
||||
|
|
@ -97,6 +98,8 @@
|
|||
|
||||
<DxMenuItem NavigateUrl="sysadmin/userproductmappings" Text="Permissions" />
|
||||
<DxMenuItem NavigateUrl="sysadmin/users" Text="Users" />
|
||||
<DxMenuItem NavigateUrl="sysadmin/blogs" Text="Blog" />
|
||||
<DxMenuItem NavigateUrl="sysadmin/manage-tours" Text="Tours" />
|
||||
</Items>
|
||||
</DxMenuItem>
|
||||
|
||||
|
|
@ -107,11 +110,11 @@
|
|||
</DxMenuItem>
|
||||
|
||||
<!--DxMenuItem Text="HotelAdmin" IconCssClass="menu-icon-support menu-icon">
|
||||
<Items>
|
||||
<DxMenuItem NavigateUrl="user/hoteladmin/" Text="Dashboard" />
|
||||
<DxMenuItem NavigateUrl="user/createAndManageTransfer" Text="Transfers" />
|
||||
<DxMenuItem NavigateUrl="user/serviceprovider/5453-a87f77787d-khj899" Text="Manage hotel" />
|
||||
</Items>
|
||||
<Items>
|
||||
<DxMenuItem NavigateUrl="user/hoteladmin/" Text="Dashboard" />
|
||||
<DxMenuItem NavigateUrl="user/createAndManageTransfer" Text="Transfers" />
|
||||
<DxMenuItem NavigateUrl="user/serviceprovider/5453-a87f77787d-khj899" Text="Manage hotel" />
|
||||
</Items>
|
||||
</DxMenuItem-->
|
||||
@* <DxMenuItem NavigateUrl="user/messages" Text="Messages" IconCssClass="fa-solid fa-envelope" /> *@
|
||||
@{
|
||||
|
|
@ -153,6 +156,7 @@
|
|||
private bool expandHotelAdminNav = false;
|
||||
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private bool myUser = false;
|
||||
private bool userHasCompany;
|
||||
private bool userHasHotels;
|
||||
private bool IsDriver;
|
||||
|
|
@ -237,4 +241,56 @@
|
|||
await SessionService.ClearAll();
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
base.OnAfterRender(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
componentUpdateService.GetOrAddComponent<AdminNavMenu>().RefreshRequested += RefreshMe;
|
||||
}
|
||||
|
||||
private void RefreshMe()
|
||||
{
|
||||
_logger.Debug($"Navbar refresh called! {DateTime.Now} ");
|
||||
|
||||
//OnInitialized();
|
||||
InitUser();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void InitUser()
|
||||
{
|
||||
if (SessionService.User != null)
|
||||
{
|
||||
myUser = true;
|
||||
userId = SessionService.User.UserId;
|
||||
userEmail = SessionService.User.Email;
|
||||
|
||||
if (SessionService.User.UserModelDto.ProfileDto.FullName != null)
|
||||
{
|
||||
userFullName = SessionService.User.UserModelDto.ProfileDto.FullName!;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"Navbar myUser false! {DateTime.Now} ");
|
||||
myUser = false;
|
||||
}
|
||||
|
||||
var properties = SessionService.User?.HasProperties;
|
||||
if (properties == null) return;
|
||||
|
||||
userHasCompany = SessionService.HasCompany;
|
||||
userHasHotels = properties.Count > 0;
|
||||
IsSysAdmin = SessionService.IsSysAdmin;
|
||||
IsDevAdmin = SessionService.IsDevAdmin;
|
||||
IsDriver = SessionService.IsDriver;
|
||||
driverPermissionId = SessionService.DriverPersmissionId;
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
_logger.Detail($"First property: {property.Value} ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Blazor.AnimateOnScroll" Version="1.1.0" />
|
||||
<PackageReference Include="BlazorAnimation" Version="2.2.0" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="24.1.3" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="24.2.3" />
|
||||
<PackageReference Include="MessagePack" Version="2.5.187" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.10" />
|
||||
|
|
@ -94,6 +94,9 @@
|
|||
<Content Update="Pages\User\SysAdmins\AddressDetailGridComponent.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="wwwroot\images\car.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@
|
|||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Pages\Utility\DynamicForm.razor" />
|
||||
<Content Remove="Shared\Users\NavigationHelperComponent.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<SupportedPlatform Include="browser" />
|
||||
|
|
@ -14,10 +19,10 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Blazor.AnimateOnScroll" Version="1.1.0" />
|
||||
<PackageReference Include="BlazorAnimation" Version="2.2.0" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="23.2.3" />
|
||||
<PackageReference Include="MessagePack" Version="2.5.168" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.6" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="24.1.3" />
|
||||
<PackageReference Include="MessagePack" Version="2.5.187" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -74,9 +79,39 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="Pages\RoadmapPage.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Pages\User\CardComponents\CompanyCardComponent.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Pages\User\Drivers\DriverManageCars.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Pages\User\Hotels\HotelEditTransfers.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Pages\User\SysAdmins\AddressDetailGridComponent.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="Pages\Utility\DynamicForm.razor" />
|
||||
<_ContentIncludedByDefault Remove="Shared\Users\NavigationHelperComponent.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Pages\Utility\DynamicForm.razor" />
|
||||
<None Include="Shared\Users\NavigationHelperComponent.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Pages\Utility\DynamicForm.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Shared\Users\NavigationHelperComponent.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@
|
|||
body {
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
/*background-color: #e7e6f7;
|
||||
background: url('../images/bg.jpg');*/
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
color: #58457b;
|
||||
--bs-border-radius: 20px;
|
||||
}
|
||||
|
||||
|
||||
.content {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
|
|
@ -25,8 +23,8 @@ body {
|
|||
}
|
||||
|
||||
.container-fluid {
|
||||
padding-left:40px;
|
||||
padding-right: 40px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
|
|
@ -134,11 +132,12 @@ select {
|
|||
}
|
||||
|
||||
.bg-gradient {
|
||||
|
||||
color: #fff !important;
|
||||
background: linear-gradient(111deg,deepskyblue,darkviolet,#502caf) !important;
|
||||
background-size: 180% 180% !important;
|
||||
animation: gradient-animation 3s ease infinite !important;
|
||||
background-image: linear-gradient(21deg, deepskyblue, #6f42c1, #af2c53) !important;
|
||||
/* background-size: 180% 180% !important; */
|
||||
animation: gradient-animation 5s ease infinite !important;
|
||||
background-attachment: fixed;
|
||||
background-blend-mode: color;
|
||||
}
|
||||
|
||||
@keyframes gradient-animation {
|
||||
|
|
@ -279,11 +278,8 @@ select {
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dxbl-grid .dxbl-grid-empty-data {
|
||||
|
||||
padding: 5px;
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
.dxbl-text-edit .dxbl-text-edit-input {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
.dxbl-tabs.dxbl-tabs-top > .dxbl-tabs-tablist {
|
||||
|
|
@ -581,6 +577,213 @@ select:focus-visible {
|
|||
|
||||
/*End Hero Carousel*/
|
||||
|
||||
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 5px 50px;*/
|
||||
}
|
||||
|
||||
.game-section .owl-stage {
|
||||
margin: 15px 0;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 15px 60px;
|
||||
width: 320px;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
align-items: flex-end;
|
||||
-webkit-align-items: flex-end;
|
||||
background: #343434 no-repeat center center / cover;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 500px;
|
||||
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
-webkit-box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.57 );
|
||||
}
|
||||
|
||||
.game-section .item:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
padding: 0 24px 12px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
transform: translateY(calc(100% - 54px));
|
||||
-webkit-transform: translateY(calc(100% - 54px));
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
.game-section .item.active .item-desc {
|
||||
transform: none;
|
||||
-webkit-transform: none;
|
||||
}
|
||||
|
||||
.game-section .item-desc p {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(32px);
|
||||
transform: translateY(32px);
|
||||
transition: all 0.4s ease-in-out 0.2s;
|
||||
-webkit-transition: all 0.4s ease-in-out 0.2s;
|
||||
}
|
||||
|
||||
.game-section .item.active .item-desc p {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.game-section .owl-theme.custom-carousel .owl-dots {
|
||||
margin-top: -20px;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
/******** Middle section CSS End *******/
|
||||
|
||||
/***** responsive css Start ******/
|
||||
|
||||
@media (min-width: 992px) and (max-width: 1199px) {
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 50px 5px;*/
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 12px 60px;
|
||||
width: 260px;
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
transform: translateY(calc(100% - 46px));
|
||||
-webkit-transform: translateY(calc(100% - 46px));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.line-title {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
/*padding: 50px 5px 40px;*/
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 12px 60px;
|
||||
width: 240px;
|
||||
height: 330px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
transform: translateY(calc(100% - 42px));
|
||||
-webkit-transform: translateY(calc(100% - 42px));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 19px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.line-title {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
/* -------- Landing page ------- */
|
||||
.game-section {
|
||||
padding: 30px 15px 20px;
|
||||
}
|
||||
|
||||
.game-section .item {
|
||||
margin: 0 10px 40px;
|
||||
width: 200px;
|
||||
height: 280px;
|
||||
}
|
||||
|
||||
.game-section .item.active {
|
||||
width: 270px;
|
||||
box-shadow: 6px 10px 10px rgba(0, 0, 0, 0.25);
|
||||
-webkit-box-shadow: 6px 10px 10px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.game-section .item-desc {
|
||||
padding: 0 14px 5px;
|
||||
transform: translateY(calc(100% - 42px));
|
||||
-webkit-transform: translateY(calc(100% - 42px));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*Admin*/
|
||||
|
||||
.gradient-custom-2 {
|
||||
|
|
@ -687,4 +890,6 @@ select:focus-visible {
|
|||
min-height: 65px;
|
||||
}
|
||||
|
||||
/*Admin end*/
|
||||
/*Admin end*/
|
||||
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -57,7 +57,9 @@ builder.Services.AddSingleton<ExchangeRateService>();
|
|||
builder.Services.AddSingleton<SmartyStreetsService>();
|
||||
builder.Services.AddSingleton<GooglePlacesService>();
|
||||
builder.Services.AddSingleton<PageHistoryState>();
|
||||
//builder.Services.AddSingleton<BrowserConsoleLogWriter>();
|
||||
builder.Services.AddScoped<BlogService>();
|
||||
builder.Services.AddScoped<TourService>();
|
||||
//builder.Services.AddScoped<BrowserConsoleLogWriter>();
|
||||
|
||||
//WebSpecific end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<PublishProvider>FileSystem</PublishProvider>
|
||||
<PublishUrl>D:\REPOS\AYCODE\Publish\ServerRelease</PublishUrl>
|
||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<ProjectGuid>2091d897-ba49-4fc1-808f-036fa040376e</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -3,6 +3,7 @@ using TIAM.Entities.Emails;
|
|||
//using TIAM.Entities.TransferDestinations;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using TIAMWebApp.Shared.Application.Models.ClientSide.UI.WizardModels;
|
||||
using EmailMessage = TIAM.Entities.Emails.EmailMessage;
|
||||
|
||||
namespace TIAMWebApp.Client.Services
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ActiveDebugProfile>http</ActiveDebugProfile>
|
||||
<ActiveDebugProfile>https</ActiveDebugProfile>
|
||||
<NameOfLastUsedPublishProfile>D:\REPOS\AYCODE\source\TourIAm\TIAMWebApp\Client\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,213 @@
|
|||
using GoogleApi.Entities.Search.Video.Common;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
|
||||
namespace TIAMWebApp.Server.Controllers
|
||||
{
|
||||
|
||||
[ApiController]
|
||||
[Route("api/blog")]
|
||||
public class BlogAPIController : ControllerBase
|
||||
{
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly string _dataPath;
|
||||
private readonly string _coverPath;
|
||||
|
||||
public BlogAPIController(IWebHostEnvironment env)
|
||||
{
|
||||
_env = env;
|
||||
_dataPath = Path.Combine(_env.WebRootPath, "data");
|
||||
_coverPath = Path.Combine(_env.WebRootPath, "uploads", "covers");
|
||||
Directory.CreateDirectory(_dataPath);
|
||||
Directory.CreateDirectory(_coverPath);
|
||||
}
|
||||
|
||||
// ✅ Get All Posts
|
||||
[HttpGet]
|
||||
public IActionResult GetAll()
|
||||
{
|
||||
var files = Directory.GetFiles(_dataPath, "*.json");
|
||||
var posts = files.Select(file =>
|
||||
{
|
||||
var json = System.IO.File.ReadAllText(file);
|
||||
return JsonSerializer.Deserialize<BlogPostMetadata>(json);
|
||||
}).ToList();
|
||||
|
||||
return Ok(posts);
|
||||
}
|
||||
|
||||
// ✅ Get Single Post
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetById(string id)
|
||||
{
|
||||
var file = Path.Combine(_dataPath, $"{id}.json");
|
||||
if (!System.IO.File.Exists(file))
|
||||
return NotFound();
|
||||
|
||||
var json = System.IO.File.ReadAllText(file);
|
||||
var post = JsonSerializer.Deserialize<BlogPostMetadata>(json);
|
||||
return Ok(post);
|
||||
}
|
||||
|
||||
// ✅ Create Post (with optional cover upload)
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromForm] BlogPostForm form)
|
||||
{
|
||||
var post = new BlogPostMetadata
|
||||
{
|
||||
Title = form.Title,
|
||||
Lead = form.Lead,
|
||||
DriveLink = form.DriveLink,
|
||||
Tags = form.Tags.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList()
|
||||
};
|
||||
|
||||
if (form.CoverImage != null)
|
||||
{
|
||||
string fileName = $"{post.Id}{Path.GetExtension(form.CoverImage.FileName)}";
|
||||
string filePath = Path.Combine(_coverPath, fileName);
|
||||
await using var fs = System.IO.File.Create(filePath);
|
||||
await form.CoverImage.CopyToAsync(fs);
|
||||
post.CoverImage = $"/uploads/covers/{fileName}";
|
||||
}
|
||||
|
||||
string jsonPath = Path.Combine(_dataPath, $"{post.Id}.json");
|
||||
await System.IO.File.WriteAllTextAsync(jsonPath, JsonSerializer.Serialize(post));
|
||||
|
||||
return Ok(post);
|
||||
}
|
||||
|
||||
//// ✅ Update Post
|
||||
//[HttpPut("{id}")]
|
||||
//public async Task<IActionResult> Update(string id, [FromBody] BlogPostMetadata post)
|
||||
//{
|
||||
// string jsonPath = Path.Combine(_dataPath, $"{id}.json");
|
||||
// if (!System.IO.File.Exists(jsonPath))
|
||||
// return NotFound();
|
||||
|
||||
// post.Id = id; // Ensure correct ID
|
||||
// await System.IO.File.WriteAllTextAsync(jsonPath, JsonSerializer.Serialize(post));
|
||||
// return Ok(post);
|
||||
//}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> Update(string id)
|
||||
{
|
||||
var form = await Request.ReadFormAsync();
|
||||
|
||||
// Parse metadata fields
|
||||
var title = form["Title"].ToString();
|
||||
var lead = form["Lead"].ToString();
|
||||
var tags = form["Tags"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList();
|
||||
var driveLink = form["DriveLink"].ToString();
|
||||
|
||||
string coverImagePath = null;
|
||||
var file = form.Files.GetFile("CoverImage");
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
var ext = Path.GetExtension(file.FileName);
|
||||
var fileName = $"{id}{ext}";
|
||||
var filePath = Path.Combine(_coverPath, fileName);
|
||||
|
||||
using var stream = System.IO.File.Create(filePath);
|
||||
await file.CopyToAsync(stream);
|
||||
|
||||
// Save relative path
|
||||
coverImagePath = $"/uploads/covers/{fileName}";
|
||||
}
|
||||
|
||||
// Load existing metadata
|
||||
string jsonPath = Path.Combine(_dataPath, $"{id}.json");
|
||||
if (!System.IO.File.Exists(jsonPath))
|
||||
return NotFound();
|
||||
|
||||
var existingJson = await System.IO.File.ReadAllTextAsync(jsonPath);
|
||||
var existing = JsonSerializer.Deserialize<BlogPostMetadata>(existingJson);
|
||||
|
||||
// Update values
|
||||
existing.Title = title;
|
||||
existing.Lead = lead;
|
||||
existing.Tags = tags;
|
||||
existing.DriveLink = driveLink;
|
||||
existing.CoverImage = coverImagePath;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(coverImagePath))
|
||||
existing.CoverImage = coverImagePath;
|
||||
|
||||
await System.IO.File.WriteAllTextAsync(jsonPath, JsonSerializer.Serialize(existing));
|
||||
return Ok(existing);
|
||||
}
|
||||
|
||||
|
||||
// ✅ Delete Post
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult Delete(string id)
|
||||
{
|
||||
string jsonPath = Path.Combine(_dataPath, $"{id}.json");
|
||||
if (!System.IO.File.Exists(jsonPath))
|
||||
return NotFound();
|
||||
|
||||
var post = JsonSerializer.Deserialize<BlogPostMetadata>(System.IO.File.ReadAllText(jsonPath));
|
||||
if (!string.IsNullOrEmpty(post?.CoverImage))
|
||||
{
|
||||
var coverPath = Path.Combine(_env.WebRootPath, post.CoverImage.TrimStart('/').Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||||
if (System.IO.File.Exists(coverPath))
|
||||
System.IO.File.Delete(coverPath);
|
||||
}
|
||||
|
||||
System.IO.File.Delete(jsonPath);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("postcontent/{postId}")]
|
||||
public async Task<IActionResult> GetPostContent(string postId)
|
||||
{
|
||||
// Load metadata (adjust this to your actual metadata loading logic)
|
||||
var metadataPath = Path.Combine(_dataPath, $"{postId}.json");
|
||||
if (!System.IO.File.Exists(metadataPath))
|
||||
{
|
||||
return NotFound("Post metadata not found.");
|
||||
}
|
||||
|
||||
var metadataJson = await System.IO.File.ReadAllTextAsync(metadataPath);
|
||||
var metadata = System.Text.Json.JsonSerializer.Deserialize<BlogPostMetadata>(metadataJson);
|
||||
if (metadata == null || string.IsNullOrEmpty(metadata.DriveLink))
|
||||
{
|
||||
return BadRequest("Invalid post metadata.");
|
||||
}
|
||||
|
||||
// Extract file ID from Google Drive link
|
||||
string? fileId = ExtractGoogleDriveFileId(metadata.DriveLink);
|
||||
if (string.IsNullOrEmpty(fileId))
|
||||
{
|
||||
return BadRequest("Invalid Drive link.");
|
||||
}
|
||||
|
||||
// Download blog content from Drive
|
||||
string downloadUrl = $"https://drive.google.com/uc?export=download&id={fileId}";
|
||||
using var httpClient = new HttpClient();
|
||||
var content = await httpClient.GetStringAsync(downloadUrl);
|
||||
|
||||
return Content(content, "text/html");
|
||||
}
|
||||
|
||||
private string? ExtractGoogleDriveFileId(string driveLink)
|
||||
{
|
||||
var match = Regex.Match(driveLink, @"\/d\/([^\/]+)");
|
||||
return match.Success ? match.Groups[1].Value : null;
|
||||
}
|
||||
|
||||
public class BlogPostForm
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Lead { get; set; }
|
||||
public string DriveLink { get; set; }
|
||||
public string Tags { get; set; }
|
||||
public IFormFile CoverImage { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
using GoogleApi.Entities.Maps.Routes.Common;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json;
|
||||
using TIAM.Entities.Transfers;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
namespace TIAMWebApp.Server.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/tours")]
|
||||
public class TourAPIController : ControllerBase
|
||||
{
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly string _toursPath;
|
||||
private readonly string _coverPath;
|
||||
|
||||
public TourAPIController(IWebHostEnvironment env)
|
||||
{
|
||||
_env = env;
|
||||
_toursPath = Path.Combine(_env.WebRootPath, "data", "tours");
|
||||
_coverPath = Path.Combine(_env.WebRootPath, "uploads", "tourcovers");
|
||||
Directory.CreateDirectory(_toursPath);
|
||||
Directory.CreateDirectory(_coverPath);
|
||||
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<TourInfo>> GetAll()
|
||||
{
|
||||
var files = Directory.GetFiles(_toursPath, "*.json");
|
||||
var tours = files.Select(file =>
|
||||
{
|
||||
var json = System.IO.File.ReadAllText(file);
|
||||
return JsonSerializer.Deserialize<TourInfo>(json);
|
||||
}).Where(t => t != null).ToList();
|
||||
|
||||
return Ok(tours);
|
||||
}
|
||||
|
||||
[HttpGet("{transferDestinationId}")]
|
||||
public ActionResult<TourInfo> Get(Guid transferDestinationId)
|
||||
{
|
||||
var path = GetPath(transferDestinationId);
|
||||
if (!System.IO.File.Exists(path))
|
||||
return NotFound();
|
||||
|
||||
var json = System.IO.File.ReadAllText(path);
|
||||
var tour = JsonSerializer.Deserialize<TourInfo>(json);
|
||||
return Ok(tour);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromForm] TourForm form)
|
||||
{
|
||||
var tour = new TourInfo
|
||||
{
|
||||
TransferDestinationId = Guid.Parse(form.TransferDestinationId),
|
||||
Title = form.Title,
|
||||
FancyDescription = form.Description,
|
||||
Created = DateTime.UtcNow,
|
||||
Modified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
// Save cover image if exists
|
||||
if (form.CoverImage != null)
|
||||
{
|
||||
string fileName = $"{tour.TransferDestinationId}{Path.GetExtension(form.CoverImage.FileName)}";
|
||||
string savePath = Path.Combine(_coverPath, fileName);
|
||||
|
||||
Directory.CreateDirectory(_coverPath); // Ensure folder exists
|
||||
|
||||
await using var fs = System.IO.File.Create(savePath);
|
||||
await form.CoverImage.CopyToAsync(fs);
|
||||
|
||||
tour.CoverImageUrl = $"/uploads/tourcovers/{fileName}";
|
||||
}
|
||||
|
||||
// Save metadata as JSON
|
||||
var jsonPath = GetPath(tour.TransferDestinationId);
|
||||
var json = JsonSerializer.Serialize(tour, new JsonSerializerOptions { WriteIndented = true });
|
||||
|
||||
await System.IO.File.WriteAllTextAsync(jsonPath, json);
|
||||
|
||||
return Ok(tour);
|
||||
}
|
||||
|
||||
[HttpPut("{transferDestinationId}")]
|
||||
public async Task<IActionResult> Update(Guid transferDestinationId, [FromBody] TourInfo updated)
|
||||
{
|
||||
var path = GetPath(transferDestinationId);
|
||||
if (!System.IO.File.Exists(path))
|
||||
return NotFound();
|
||||
|
||||
updated.TransferDestinationId = transferDestinationId;
|
||||
updated.Modified = DateTime.UtcNow;
|
||||
|
||||
var json = JsonSerializer.Serialize(updated, new JsonSerializerOptions { WriteIndented = true });
|
||||
await System.IO.File.WriteAllTextAsync(path, json);
|
||||
|
||||
return Ok(updated);
|
||||
}
|
||||
|
||||
[HttpDelete("{transferDestinationId}")]
|
||||
public IActionResult Delete(Guid transferDestinationId)
|
||||
{
|
||||
var path = GetPath(transferDestinationId);
|
||||
if (!System.IO.File.Exists(path))
|
||||
return NotFound();
|
||||
|
||||
System.IO.File.Delete(path);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
//[HttpPost("{id}/image")]
|
||||
//public async Task<IActionResult> UploadTourImage(Guid id, IFormFile file)
|
||||
//{
|
||||
// if (file == null || file.Length == 0)
|
||||
// return BadRequest("No file uploaded.");
|
||||
|
||||
// var ext = Path.GetExtension(file.FileName);
|
||||
// var fileName = $"{id}{ext}";
|
||||
// var filePath = Path.Combine(_coverPath, fileName);
|
||||
// Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
|
||||
|
||||
// using var stream = System.IO.File.Create(filePath);
|
||||
// await file.CopyToAsync(stream);
|
||||
|
||||
// // Optionally: update metadata to store file path (e.g., in a JSON file or DB)
|
||||
|
||||
// return Ok();
|
||||
//}
|
||||
|
||||
[HttpPost("{id}/image")]
|
||||
public async Task<IActionResult> UploadTourImage(Guid id, IFormFile file)
|
||||
{
|
||||
if (file == null || file.Length == 0)
|
||||
return BadRequest("No file uploaded.");
|
||||
|
||||
var ext = Path.GetExtension(file.FileName);
|
||||
var fileName = $"{id}{ext}";
|
||||
//var folderPath = Path.Combine("wwwroot", "uploads", "tours", id.ToString());
|
||||
//Directory.CreateDirectory(folderPath);
|
||||
|
||||
var filePath = Path.Combine(_coverPath, fileName);
|
||||
|
||||
using var stream = System.IO.File.Create(filePath);
|
||||
await file.CopyToAsync(stream);
|
||||
|
||||
// ✅ Update TourInfo JSON
|
||||
var jsonPath = GetPath(id); // Same as in your PUT method
|
||||
if (!System.IO.File.Exists(jsonPath))
|
||||
return NotFound("TourInfo JSON not found.");
|
||||
|
||||
var json = await System.IO.File.ReadAllTextAsync(jsonPath);
|
||||
var tour = JsonSerializer.Deserialize<TourInfo>(json);
|
||||
|
||||
// Relative path to serve the image (adjust if needed)
|
||||
var relativeImagePath = Path.Combine("uploads", "tourcovers", fileName).Replace("\\", "/");
|
||||
|
||||
tour!.CoverImageUrl = "/" + relativeImagePath;
|
||||
tour.Modified = DateTime.UtcNow;
|
||||
|
||||
var updatedJson = JsonSerializer.Serialize(tour, new JsonSerializerOptions { WriteIndented = true });
|
||||
await System.IO.File.WriteAllTextAsync(jsonPath, updatedJson);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private string GetPath(Guid id) =>
|
||||
Path.Combine(_toursPath, $"{id}.json");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -90,11 +90,12 @@ namespace TIAMWebApp.Server.Controllers
|
|||
}
|
||||
|
||||
//[Authorize]
|
||||
//[HttpGet]
|
||||
//[Route(APIUrls.GetTransferDriversByTransferIdRouteName)]
|
||||
[NonAction]
|
||||
//[NonAction]
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
[Route(APIUrls.GetTransferDestinationByIdRouteName)]
|
||||
[SignalR(SignalRTags.GetTransferDestinationById)]
|
||||
public async Task<TransferDestination?> GetTransferDestinationById(Guid transferDestinationId)
|
||||
public async Task<TransferDestination?> GetTransferDestinationById([FromBody] Guid transferDestinationId)
|
||||
{
|
||||
var transferDestination = await _adminDal.GetTransferDestinationByIdAsync(transferDestinationId);
|
||||
return transferDestination;
|
||||
|
|
@ -108,6 +109,15 @@ namespace TIAMWebApp.Server.Controllers
|
|||
return null;// await _transferDestinationDal.Context.TransferDestinations.FirstOrDefaultAsync(x => x.Latitude == latitude && x.Longitude == longitude);
|
||||
}
|
||||
|
||||
//[AllowAnonymous]
|
||||
//[HttpGet]
|
||||
//[Route(APIUrls.GetTransferDestinationById)]
|
||||
//public async Task<TransferDestination?> GetTransferDestinationById(Guid )
|
||||
//{
|
||||
// var transferDestination = await _adminDal.GetTransferDestinationByIdAsync(transferDestinationId);
|
||||
// return transferDestination;
|
||||
//}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
[Route("GetTransferDestinationByAddress")]
|
||||
|
|
@ -494,10 +504,10 @@ namespace TIAMWebApp.Server.Controllers
|
|||
{
|
||||
if (!transfer.ProductId.IsNullOrEmpty())
|
||||
{
|
||||
var product = await _adminDal.GetProductByIdAsync((Guid)transfer.ProductId);
|
||||
//var product = await _adminDal.GetProductByIdAsync((Guid)transfer.ProductId);
|
||||
transfer.Price = _transferBackendService.GetTransferPrice(transfer.ProductId.Value, from, to, transfer.PassengerCount);
|
||||
|
||||
if (transfer.Price.HasValue && transfer.Price > 0)
|
||||
if (transfer.Price is > 0)
|
||||
{
|
||||
transfer.Revenue = _transferBackendService.GetCommission((Guid)transfer.ProductId, (double)transfer.Price, to);
|
||||
}
|
||||
|
|
@ -766,6 +776,9 @@ namespace TIAMWebApp.Server.Controllers
|
|||
_logger.Debug($"GetTransferDrivers called; transferId: {transferId}");
|
||||
|
||||
var result = await _adminDal.GetTransferToDriversByTransferIdAsync(transferId);
|
||||
|
||||
//System.IO.File.WriteAllText($"h://TiamJsons//{transferId}.json", result.ToJson());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,13 @@ namespace TIAMWebApp.Server.Controllers
|
|||
if (!loggedInModel.IsLoggedIn)
|
||||
{
|
||||
_logger.Warning(@"User not valid! errorCode: " + loggedInModel.LoginErrorCode);
|
||||
return null;
|
||||
//return null;
|
||||
return new MainResponse
|
||||
{
|
||||
Content = loggedInModel.LoginErrorCode,
|
||||
IsSuccess = false,
|
||||
ErrorMessage = "Not valid login."
|
||||
};
|
||||
}
|
||||
|
||||
var response = new MainResponse
|
||||
|
|
@ -550,7 +556,7 @@ namespace TIAMWebApp.Server.Controllers
|
|||
//send email
|
||||
|
||||
_logger.Info($"Created transfer, send emailMessage!!!");
|
||||
var message = new MessageSenderModel<EmailMessage>();
|
||||
var message = new MessageSenderModel<TIAM.Entities.Emails.EmailMessage>();
|
||||
message.Message = new EmailMessage();
|
||||
message.Message.EmailAddress = email;
|
||||
message.Message.Id = Guid.NewGuid();
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ builder.Services.AddCors(options =>
|
|||
{
|
||||
options.AddPolicy(myAllowSpecificOrigins, policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin();
|
||||
policy.WithOrigins("http://touriam.com",
|
||||
"http://www.touriam.com");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.22" />
|
||||
<PackageReference Include="QRCoderNetCore" Version="1.0.0" />
|
||||
<PackageReference Include="SendGrid" Version="9.29.3" />
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.9.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.9.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.9.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ActiveDebugProfile>https</ActiveDebugProfile>
|
||||
<NameOfLastUsedPublishProfile>C:\REPOS\AYCODE\source\TourIAm\TIAMWebApp\Server\Properties\PublishProfiles\ReleaseDeployProfile.pubxml</NameOfLastUsedPublishProfile>
|
||||
<NameOfLastUsedPublishProfile>D:\REPOS\AYCODE\source\TourIAm\TIAMWebApp\Server\Properties\PublishProfiles\ReleaseDeployProfile.pubxml</NameOfLastUsedPublishProfile>
|
||||
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DeveloperDbConnection": "Data Source=185.51.190.197;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=Anata_Development_Team;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
//"DeveloperDbConnection": "Data Source=185.51.190.197;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=Anata_Development_Team;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
|
||||
//"DeveloperDbConnection": "Data Source=194.164.235.47;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=Anata_Development_Team;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
"DeveloperDbConnection": "Data Source=195.26.231.218;Initial Catalog=TIAM_DEV;Trusted_Connection=false;Encrypt=false;TrustServerCertificate=True;Connect Timeout=200;User ID=sa;Password=v6f_?xNfg9N1;MultipleActiveResultSets=true"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Id": "00000000-0000-0000-0000-000000000000",
|
||||
"TransferDestinationId": "171fcca4-ffd5-4380-9402-f27447af1e08",
|
||||
"Title": "Downtown",
|
||||
"FancyDescription": "fdshjklhsjfkslh dfjkhsjklfhd jkkslhfdsjkfh dskfh dsklhf dsjkl fdhjkl fdshjk fkjld hlkdskl dsjk fdjlfh dskh fdsjkfdshl khf dk hldsk hldskh dsjk hdslkf dhjkh dsfk fdslsk",
|
||||
"CoverImageUrl": "/uploads/tourcovers/171fcca4-ffd5-4380-9402-f27447af1e08.png",
|
||||
"Created": "2025-07-28T06:29:35.6626494Z",
|
||||
"Modified": "2025-07-28T06:29:35.6626499Z"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Id": "00000000-0000-0000-0000-000000000000",
|
||||
"TransferDestinationId": "72a29052-0d99-49ec-a103-3b5ca86b5b4c",
|
||||
"Title": "Rept\u00E9ri t\u00FAra",
|
||||
"FancyDescription": "jhkl hjk hjfdsklh sjklfh sjkfh sjklfhdsjlfh djkf hdjklf hjk fldshjkf hdsjkf hdjk fhdsjkf hdsjklfhdjklf dhjkf hdsjklfdhjkldsfh jklsdfhjkfslhfjkslh fdsklh fjklhfdsjklhdsjkfdshjkfdhjksdlhjksdh skl",
|
||||
"CoverImageUrl": "/uploads/tourcovers/72a29052-0d99-49ec-a103-3b5ca86b5b4c.jpeg",
|
||||
"Created": "2025-07-27T18:05:27.5184619Z",
|
||||
"Modified": "2025-07-27T18:05:27.5184622Z"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Id": "00000000-0000-0000-0000-000000000000",
|
||||
"TransferDestinationId": "ac30e313-6752-4358-b686-65a57be7a030",
|
||||
"Title": "T\u00FAra 2",
|
||||
"FancyDescription": "jkhk lhjdh fksldh fjk hsfjklh jdskhfsjk fhdsjk fhsjklfhsjlhf dsjkh fdsjklfh sjklhf sjdkhf sjklhfsjkfh dsjklhf dsjk hfdsjklhfdsklhfjdkslhfdsjklhf dsjklhf dsjkl hfdslh fdsjkh fsjkl hfdsjklfh sjkh fdskh fdkslfhjkshfdsl hfdskl",
|
||||
"CoverImageUrl": "/uploads/tourcovers/ac30e313-6752-4358-b686-65a57be7a030.jpeg",
|
||||
"Created": "2025-07-27T16:24:56.1635945Z",
|
||||
"Modified": "2025-07-27T16:24:56.1635947Z"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Id": "00000000-0000-0000-0000-000000000000",
|
||||
"TransferDestinationId": "ae7c3d59-e9fb-4393-a89c-3124ed5eba04",
|
||||
"Title": "Valami",
|
||||
"FancyDescription": "jkhjdkhfjkdhfjsklhf jskh fsjdklfh sjkh fsjdk hfdsjkh fdsk hfdskl hdfsjkh fjdsklfh jdkl hfjkdslhfdjskh fdjsk hfsjklfh sdjh fdsjklfh sjk hfjklh fsjklhdls",
|
||||
"CoverImageUrl": "/uploads/tourcovers/ae7c3d59-e9fb-4393-a89c-3124ed5eba04.jpeg",
|
||||
"Created": "0001-01-01T00:00:00",
|
||||
"Modified": "2025-07-28T06:26:09.0304045Z"
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.6 MiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
|
@ -1,4 +1,5 @@
|
|||
using TIAM.Entities.Emails;
|
||||
using EmailMessage = TIAM.Entities.Emails.EmailMessage;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Interfaces
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace TIAMWebApp.Shared.Application.Interfaces
|
|||
Task<List<TransferDestination>> GetDestinationsAsync();
|
||||
Task<TransferDestination?> GetTransferDestinationbyCoordinatesAsync(string destinationId);
|
||||
Task<TransferDestination?> GetTransferDestinationbyAddressAsync(string destinationId);
|
||||
Task<TransferDestination?> GetTransferDestinationbyIdAsync(Guid destinationId);
|
||||
Task<TransferDestination?> CreateTransferDestination(TransferDestination model);
|
||||
|
||||
Task<TransferDestination?> UpdateTransferDestination(TransferDestination model);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ namespace TIAMWebApp.Shared.Application.Models
|
|||
public const string GetTransferDestinationByAddressRouteName = "GetTransferDestinationByAddress";
|
||||
public const string GetTransferDestinationByAddress = TransferDataAPI + GetTransferDestinationByAddressRouteName;
|
||||
|
||||
public const string GetTransferDestinationByIdRouteName = "GetTransferDestinationById";
|
||||
public const string GetTransferDestinationById = TransferDataAPI + GetTransferDestinationByIdRouteName;
|
||||
|
||||
public const string CreateTransferDestinationRouteName = "CreateTransferDestination";
|
||||
public const string CreateTransferDestination = TransferDataAPI + CreateTransferDestinationRouteName;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class BlogPostMetadata
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
public string Title { get; set; }
|
||||
public string Lead { get; set; }
|
||||
public string DriveLink { get; set; }
|
||||
public string CoverImage { get; set; } // Relative URL
|
||||
public List<string> Tags { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,10 +8,10 @@ namespace TIAMWebApp.Shared.Application.Models.ClientSide
|
|||
//public static string BaseUrl = "https://touriam.mangoweb.hu";
|
||||
//public static string ApiBaseUrl = "https://touriam.mangoweb.hu";
|
||||
#if RELEASE
|
||||
public static string BaseUrl = "https://test.touriam.com";
|
||||
public static string ApiBaseUrl = "https://test.touriam.com";
|
||||
//public static string BaseUrl = "https://touriam.com";
|
||||
//public static string ApiBaseUrl = "https://touriam.com";
|
||||
//public static string BaseUrl = "https://test.touriam.com";
|
||||
//public static string ApiBaseUrl = "https://test.touriam.com";
|
||||
public static string BaseUrl = "https://touriam.com";
|
||||
public static string ApiBaseUrl = "https://touriam.com";
|
||||
//public static string BaseUrl = "https://qa.touriam.com";
|
||||
//public static string ApiBaseUrl = "https://qa.touriam.com";
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class TourForm
|
||||
{
|
||||
public string TransferDestinationId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public IFormFile? CoverImage { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class TourInfo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TransferDestinationId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string? FancyDescription { get; set; }
|
||||
public string? CoverImageUrl { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime Modified { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
using AyCode.Core.Consts;
|
||||
using AyCode.Core.Helpers;
|
||||
using AyCode.Services.Loggers;
|
||||
using AyCode.Services.SignalRs;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TIAM.Entities.Drivers;
|
||||
using TIAM.Entities.Transfers;
|
||||
|
|
@ -107,10 +108,8 @@ namespace TIAMWebApp.Shared.Application.Services
|
|||
}
|
||||
|
||||
public async Task<List<TransferToDriver>> GetTransferDrivers(Guid transferId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
=> await GetByIdAsync<List<TransferToDriver>>(SignalRTags.GetTransferDriversByTransferId, transferId) ?? [];
|
||||
|
||||
public async Task<TransferToDriver?> AddTransferDriver(TransferToDriver transferToDriver)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Services
|
||||
{
|
||||
|
||||
public class BlogService
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
|
||||
public BlogService(HttpClient http)
|
||||
{
|
||||
_http = http;
|
||||
}
|
||||
|
||||
public async Task<List<BlogPostMetadata>> GetAllPostsAsync()
|
||||
{
|
||||
return await _http.GetFromJsonAsync<List<BlogPostMetadata>>("/api/blog") ?? new();
|
||||
}
|
||||
|
||||
public async Task<BlogPostMetadata?> GetPostByIdAsync(string id)
|
||||
{
|
||||
return await _http.GetFromJsonAsync<BlogPostMetadata>($"/api/blog/{id}");
|
||||
}
|
||||
|
||||
public async Task<BlogPostMetadata?> CreatePostAsync(BlogPostMetadata metadata, IBrowserFile? coverImage)
|
||||
{
|
||||
using var content = new MultipartFormDataContent();
|
||||
content.Add(new StringContent(metadata.Title ?? ""), "Title");
|
||||
content.Add(new StringContent(metadata.Lead ?? ""), "Lead");
|
||||
content.Add(new StringContent(metadata.DriveLink ?? ""), "DriveLink");
|
||||
content.Add(new StringContent(string.Join(",", metadata.Tags ?? new())), "Tags");
|
||||
|
||||
if (coverImage != null)
|
||||
{
|
||||
var fileContent = new StreamContent(coverImage.OpenReadStream(long.MaxValue));
|
||||
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(coverImage.ContentType);
|
||||
content.Add(fileContent, "CoverImage", coverImage.Name);
|
||||
}
|
||||
|
||||
var response = await _http.PostAsync("/api/blog", content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<BlogPostMetadata>();
|
||||
}
|
||||
|
||||
public async Task UpdatePostAsync(BlogPostMetadata metadata, IBrowserFile? newImageFile = null)
|
||||
{
|
||||
using var content = new MultipartFormDataContent();
|
||||
|
||||
content.Add(new StringContent(metadata.Title ?? ""), "Title");
|
||||
content.Add(new StringContent(metadata.Lead ?? ""), "Lead");
|
||||
content.Add(new StringContent(metadata.DriveLink ?? ""), "DriveLink");
|
||||
content.Add(new StringContent(string.Join(",", metadata.Tags ?? new List<string>())), "Tags");
|
||||
|
||||
if (newImageFile != null)
|
||||
{
|
||||
var stream = newImageFile.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024); // 10 MB max
|
||||
var fileContent = new StreamContent(stream);
|
||||
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(newImageFile.ContentType);
|
||||
content.Add(fileContent, "CoverImage", newImageFile.Name);
|
||||
}
|
||||
|
||||
var response = await _http.PutAsync($"/api/blog/{metadata.Id}", content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
|
||||
public async Task DeletePostAsync(string id)
|
||||
{
|
||||
var response = await _http.DeleteAsync($"/api/blog/{id}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||