email fix on login, override comission fix, transferorder page changed, wizard changes, custom address fix and changes

This commit is contained in:
Adam 2025-09-25 14:26:19 +02:00
parent 8b4586909f
commit d1ba700c01
21 changed files with 231 additions and 98 deletions

View File

@ -8,12 +8,14 @@ public static class TiamConstClient
public static string DefaultLocale = "en-US";
public static Guid TransferProductId = Guid.Parse("814b5495-c2e9-4f1d-a73f-37cd5d353078");
public static Guid[] DevAdminIds = new Guid[2] { Guid.Parse("dcf451d2-cc4c-4ac2-8c1f-da00041be1fd"), Guid.Parse("4cbaed43-2465-4d99-84f1-c8bc6b7025f7") };
public static Guid[] SysAdmins = new Guid[3]
public static Guid[] SysAdmins = new Guid[4]
{
Guid.Parse("dcf451d2-cc4c-4ac2-8c1f-da00041be1fd"),
Guid.Parse("4cbaed43-2465-4d99-84f1-c8bc6b7025f7"),
Guid.Parse("540271f6-c604-4c16-8160-d5a7cafedf00")
Guid.Parse("540271f6-c604-4c16-8160-d5a7cafedf00"),
Guid.Parse("18858d54-02fd-4002-98af-542b81fd3c3b")
};
public static Dictionary<string, Guid> SysAccounts = new Dictionary<string, Guid>
{
{ "SystemEmailSender", Guid.Parse("5e13e051-4fd6-4a30-a371-75cc785cfb84")},
@ -21,7 +23,7 @@ public static class TiamConstClient
public static string WelcomeEmailTemplateName = "WelcomeEmailTemplate";
public static string NewTransferEmailTemplateName = "NewTransferEmailTemplate";
public static string TransferModifiedEmailTemplateName = "TramsferModifiedEmailTemplate";
public static string TransferModifiedEmailTemplateName = "TransferModifiedEmailTemplate";
public static string ForgotPasswordEmailTemplateName = "ForgotPasswordEmailTemplate";
public static string GeneralEmailTemplateName = "GeneralEmailTemplate";

View File

@ -309,15 +309,21 @@ namespace TIAM.Services.Server
smtpClient.EnableSsl = true; // Try false for port 587
smtpClient.TargetName = $"SMTPS/{smtpHost}";
string filePath = @"C:\path\to\your\file.pdf";
var attachment = new System.Net.Mail.Attachment(filePath);
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
IsBodyHtml = true,
};
mailMessage.Attachments.Insert(0, attachment);
await smtpClient.SendMailAsync(mailMessage);
}
}

View File

@ -35,7 +35,7 @@ else
private string Address { get; set; }
private List<PredictionItem> Predictions { get; set; } = new();
private PredictionItem selectedPrediction { get; set; }
private PredictionItem selectedPrediction { get; set; } = new();
public PredictionItem SelectedPrediction
{
get => selectedPrediction;
@ -58,8 +58,12 @@ else
{
var predictions = await GooglePlacesService.GetPlacePredictionsAsync(input);
Predictions = predictions.ConvertAll(p => new PredictionItem { Description = p });
if (Predictions.Count > 0)
{
SelectedPrediction = Predictions[0];
}
else { SelectedPrediction = new(); }
}
else
{
Predictions.Clear();

View File

@ -9,7 +9,8 @@
OnInvalidSubmit="@HandleInvalidSubmit"
Context="EditFormContext">
<div class="text-center">
<h4>@localizer.GetString(TitleResourceString)</h4>
@* <h4>@localizer.GetString(TitleResourceString)</h4> *@
<h4>@TitleString</h4>
<p class="tm-8 mb-0 fw-normal fs-825">
@localizer.GetString(SubtitleResourceString)
</p>

View File

@ -1,20 +1,21 @@
using DevExpress.Blazor;
using AyCode.Core.Consts;
using AyCode.Services.Loggers;
using DevExpress.Blazor;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Localization;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;
using TIAMWebApp.Shared.Application.Utility;
using Microsoft.Extensions.Localization;
using TIAM.Resources;
using TIAMWebApp.Shared.Application.Interfaces;
using System.Reflection;
using TIAMWebApp.Shared.Application.Models;
using TIAMSharedUI.Shared;
using System.Text.RegularExpressions;
using AyCode.Core.Consts;
using TIAM.Core.Loggers;
using AyCode.Services.Loggers;
using TIAM.Entities.Products;
using TIAM.Resources;
using TIAMSharedUI.Shared;
using TIAMWebApp.Shared.Application.Interfaces;
using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Utility;
namespace TIAMSharedUI.Pages.Components
@ -38,6 +39,9 @@ namespace TIAMSharedUI.Pages.Components
[Parameter]
public string TitleResourceString { get; set; } = "Wizard";
[Parameter]
public string TitleString { get; set; } = "Wizard";
[Parameter]
public string SubtitleResourceString { get; set; } = "Let's fill in this form";
@ -56,9 +60,9 @@ namespace TIAMSharedUI.Pages.Components
[Parameter]
public string CssClass { get; set; } = "";
[Parameter] public Product? CurrentProduct { get; set; } = null;
private LoggerClient<InputWizard> _logger;
string _formSubmitResult = "";
private string _spinnerClass = "";
@ -353,34 +357,57 @@ namespace TIAMSharedUI.Pages.Components
//string.Compare(metadata.CustomDataType, "BoldRed", true) == 0
//else if (property.PropertyType == typeof(string) && property.Name == "Destination")
//else if (property.PropertyType == typeof(string) && string.Compare(attrList.CustomDataType, "TransferDestination", true) == 0)
//{
// editor.OpenComponent<SliderItemSelector>(j);
// editor.AddAttribute(j++, "OwlId", "owlSelector" + stepId);
// editor.AddAttribute(j++, "TextValue", property.GetValue(Data));
// //editor.AddAttribute(j++, "TExpression", lambda);
// editor.AddAttribute(j++, "OnSliderChanged", EventCallback.Factory.Create<string>(this, result =>
// {
// _logger.DetailConditional($"Slider changed to {result}");
// property.SetValue(Data, result);
// _logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
// //StateHasChanged(); // Add this line to refresh the UI
// }));
// editor.CloseComponent();
// editor.OpenComponent<DxTextBox>(j++);
// /*editor.AddAttribute(j++, "CssClass", "form-field");*/
// editor.AddAttribute(j++, "NullText", "Slide or type");
// editor.AddAttribute(j++, "Enabled", false);
// editor.AddAttribute(j++, "Text", property.GetValue(Data));
// editor.AddAttribute(j++, "TextExpression", lambda);
// editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str =>
// {
// property.SetValue(Data, str);
// _logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
// }));
// editor.CloseComponent();
//}
else if (property.PropertyType == typeof(string) && string.Compare(attrList.CustomDataType, "TransferDestination", true) == 0)
{
editor.OpenComponent<SliderItemSelector>(j);
editor.AddAttribute(j++, "OwlId", "owlSelector" + stepId);
editor.OpenComponent<ComboboxItemSelector>(j);
editor.AddAttribute(j++, "TextValue", property.GetValue(Data));
//editor.AddAttribute(j++, "TExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
if (CurrentProduct != null)
{
editor.AddAttribute(j++, "ProductId", CurrentProduct.Id);
}
// editor.AddAttribute(j++, "ValExpression", lambda);
editor.AddAttribute(j++, "OnSliderChanged", EventCallback.Factory.Create<string>(this, result =>
{
_logger.DetailConditional($"Slider changed to {result}");
_logger.Debug($"Slider changed to {result}");
property.SetValue(Data, result);
_logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
//StateHasChanged(); // Add this line to refresh the UI
}));
editor.CloseComponent();
editor.OpenComponent<DxTextBox>(j++);
/*editor.AddAttribute(j++, "CssClass", "form-field");*/
editor.AddAttribute(j++, "NullText", "Slide or type");
editor.AddAttribute(j++, "Enabled", false);
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str =>
{
property.SetValue(Data, str);
_logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
}));
editor.CloseComponent();
}

View File

@ -10,7 +10,7 @@
<DxMaskedInput @bind-Value="@LoginModel.Email"
Id="Email"
CssClass="cw-320"
Mask="@EmailMask"
MaskMode="MaskMode.RegEx">
<DxRegExMaskProperties MaskAutoCompleteMode="@((MaskAutoCompleteMode)AutoCompleteMode)"

View File

@ -164,7 +164,8 @@
}
}
<div class="col-12 col-md-6">
<div class="col-12 col-md-4">
<div class="card">
<DxToolbar ItemRenderStyleMode="ToolbarRenderStyleMode.Contained">
<Items>
<DxToolbarItem Alignment="ToolbarItemAlignment.Right" Text="Help" RenderStyle="ButtonRenderStyle.Secondary" IconCssClass="grid-icon-column-chooser" Click="ShowHelp_Click" />
@ -173,16 +174,20 @@
<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>
@*<DynamicEditForm Data="_myModel"
TitleString="@($"To: {tourInfo.Title}, Price: {_myModel.Price} EUR")"
isEditing="true" IgnoreReflection="_transferIgnorList1" OnSubmit="SubmitForm">
</DynamicEditForm>*@
<InputWizard Data=@_myModel
TitleString="@($"To: {tourInfo.Title}, Price: {_myModel.Price} EUR")"
OnSubmit="SubmitForm"
IgnoreReflection="@_transferIgnorList1"
SubmitButtonText="ButtonSend"
TitleResourceString="TransferTitle"
SubtitleResourceString="TransferSubtitle"></InputWizard>
</div>
</div>
@ -276,6 +281,7 @@
"PaymentId",
"FirstName",
"LastName",
"FlightNumber",
"UserProductMappingId",
"UserProductToCarId",
"ReferralId",

View File

@ -214,7 +214,9 @@
<DxFormLayoutItem Caption="Revenue:" ColSpanMd="3">
@editFormContext.GetEditor("Revenue")
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Comment:" ColSpanMd="3">
@editFormContext.GetEditor("Comment")
</DxFormLayoutItem>
</DxFormLayout>
</EditFormTemplate>

View File

@ -39,6 +39,11 @@
<InputTextArea @bind-Value="newTour.Name" class="form-control" />
</div>
<div class="mb-3">
<label>ShortDescription</label>
<InputTextArea @bind-Value="newTour.Bio" class="form-control" />
</div>
<div class="mb-3">
<label>Description</label>
<InputTextArea @bind-Value="newTour.Description" class="form-control" />
@ -78,6 +83,9 @@
<span>
<strong>@tour?.Title</strong> — @tour.FancyDescription
</span>
<span>
@tour.Bio
</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>
@ -115,9 +123,10 @@
{
TransferDestinationId = tour.TransferDestinationId,
Name = tour.Title,
Bio = tour.Bio,
Description = tour.FancyDescription,
ImageBytes = null,
ImageFileName = null
ImageFileName = tour.CoverImageUrl
};
IsEditing = true;
@ -173,6 +182,7 @@
newTour.ImageFileName = uploadedFile.Name;
}
if (IsEditing && EditingTourId.HasValue)
{
var updatedTour = new TourInfo
@ -180,8 +190,9 @@
Id = EditingTourId.Value,
TransferDestinationId = newTour.TransferDestinationId,
Title = newTour.Name,
Bio = newTour.Bio,
FancyDescription = newTour.Description,
CoverImageUrl = "" // assume your service handles image URL logic
CoverImageUrl = newTour.ImageFileName // assume your service handles image URL logic
};
await TourService.UpdateAsync(updatedTour, uploadedFile);
@ -230,6 +241,7 @@
[StringLength(100, ErrorMessage = "Tour name cannot exceed 100 characters.")]
public string Name { get; set; } = string.Empty;
public string? Bio { get; set; }
public string? Description { get; set; }
public byte[]? ImageBytes { get; set; }

View File

@ -22,7 +22,7 @@
<DxTabs SizeMode="SizeMode.Small" CssClass="bg-light">
<DxTabPage Text="Preset addresses">
@* <DxTabPage Text="Preset addresses">
<DxComboBox Data="@_destinations"
@ -37,7 +37,7 @@
SizeMode="SizeMode.Small" />
</DxTabPage>
</DxTabPage> *@
<DxTabPage Text="Custom address">
<AddressSearchAndSelectComponent AddressChanged="@OnSelectedAddressChanged" CssClass="@CssClass">
@ -56,7 +56,17 @@
</DxTabPage>
</DxTabs>
<p>Selected address: @_address</p>
@{
if (string.IsNullOrEmpty(_address))
{
<p class="text-muted mt-2">No address selected</p>
}
else
{
<p class="text-success mt-2">Selected address: @_address</p>
}
}
@* <p class="demo-text cw-480 mt-3">

View File

@ -16,16 +16,24 @@
{
foreach (var item in Tours)
{
<div class="item" style="background-image: url(@item.CoverImageUrl);">
<div class="item" style="background-image: url(@item.CoverImageUrl); height: 600px !important">
<div class="added" style="position: absolute; top: 100px; left:0px; text-align:center; padding:10px; width:100%">
<p>@item.Bio</p>
</div>
<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 style="padding-top:70px">@item.Created</p> *@
<div style="margin-top:70px; position: relative; z-index: 10; height:450px; overflow-y: scroll;">
<p style="">@item.FancyDescription</p>
</div>
@* <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>
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 1))"><i class="fa-solid fa-users"></i> 1-3</button>
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 2))"><i class="fa-solid fa-users"></i> 4-6</button>
<button class="btn btn-primary mt-auto" @onclick="@( ()=> Book(item.TransferDestinationId, 3))"><i class="fa-solid fa-users"></i> 7-8</button>
</div>
<div class="glass" style="position: absolute; top:0px; left:0px; padding:10px; width:100%">
<h4>@item.Title</h4>
</div>

View File

@ -89,12 +89,15 @@ button {
background: #e73700;
}
/******* Middle section CSS Start ******/
/* -------- Landing page ------- */
.game-section {
/*padding: 5px 50px;*/
}
.game-section .owl-stage {
margin: 15px 0;
display: flex;
@ -136,6 +139,15 @@ button {
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
}
.game-section .added {
opacity: 1;
/*font-size: x-large;*/
}
.game-section .item.active .added {
opacity: 0;
}
.game-section .item-desc {
padding: 0 24px 12px;
color: #fff;
@ -187,6 +199,8 @@ button {
line-height: 32px;
}
/* -------- Landing page ------- */
.game-section {
/*padding: 50px 5px;*/

View File

@ -117,4 +117,10 @@
<UpToDateCheckInput Remove="Shared\Users\NavigationHelperComponent.razor" />
</ItemGroup>
<ItemGroup>
<None Update="Shared\Components\ToursComponent.razor.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -686,14 +686,33 @@ namespace TIAMWebApp.Server.Controllers
var product = await _adminDal.Context.Products.FirstOrDefaultAsync(x => x.Id == transfer.ProductId);
if (product != null)
{
if (transfer.Revenue.HasValue && transfer.Revenue.Value > 0)
{
//revenue intentional override, do nothing
}
else if (!transfer.Revenue.HasValue || transfer.Revenue.Value == 0)
{
//revenue not set, calculate it
transfer.Revenue = transfer.Price * product.ServiceProvider.CommissionPercent / 100;
}
}
}
else
{
if (transfer.Revenue.HasValue && transfer.Revenue.Value > 0)
{
//revenue intentional override, do nothing
}
else if (!transfer.Revenue.HasValue || transfer.Revenue.Value == 0)
{
//revenue not set, calculate it
transfer.Revenue = _transferBackendService.GetCommission((Guid)transfer.ProductId, (double)transfer.Price, to);
}
}
}
return await _adminDal.UpdateTransferAsync(transfer);
}

View File

@ -12,8 +12,8 @@ namespace TIAMWebApp.Server.Services
{
private readonly HttpClient _httpClient;
private readonly TIAM.Core.Loggers.ILogger _logger;
private readonly string _clientId;
private readonly string _clientSecret;
private readonly string _clientId = "sup_pk_RrAkDKKDU8jFSdlCq1dmw19WuBU42LJkD";
private readonly string _clientSecret = "sup_sk_smy6IL1ww3I66adCSPzv5GkSKBFP4TNMs";
public SumupService(HttpClient httpClient, string clientId, string clientSecret, IEnumerable<IAcLogWriterBase> logWriters)
{
@ -25,6 +25,7 @@ namespace TIAMWebApp.Server.Services
public async Task<string> GetAccessTokenAsync()
{
var authToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_clientId}:{_clientSecret}"));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authToken);
@ -43,7 +44,8 @@ namespace TIAMWebApp.Server.Services
{
var accessToken = await GetAccessTokenAsync();
//_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR");
//_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_smy6IL1ww3I66adCSPzv5GkSKBFP4TNMs");
var requestContent = new StringContent(JsonSerializer.Serialize(paymentRequest), Encoding.UTF8, "application/json");
@ -65,7 +67,8 @@ namespace TIAMWebApp.Server.Services
};
var checkoutRequest = new HttpRequestMessage(HttpMethod.Post, "https://api.sumup.com/v0.1/checkouts");
checkoutRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR");
//checkoutRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR");
checkoutRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "sup_sk_smy6IL1ww3I66adCSPzv5GkSKBFP4TNMs");
var kvaanyad = JsonSerializer.Serialize(request, options);
_logger.Detail($"Request json: {kvaanyad}");
checkoutRequest.Content = new StringContent(kvaanyad, Encoding.UTF8, "application/json");
@ -89,7 +92,8 @@ namespace TIAMWebApp.Server.Services
string url = $"https://api.sumup.com/v0.1/checkouts/{checkoutId}";
// Replace with your actual access token
string accessToken = "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR";
//string accessToken = "sup_sk_0rt9IFrMpE9qA6328vqMwCtiCntRXZxGR";
string accessToken = "sup_sk_smy6IL1ww3I66adCSPzv5GkSKBFP4TNMs";
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);

File diff suppressed because one or more lines are too long

View File

@ -2,8 +2,9 @@
"Id": "00000000-0000-0000-0000-000000000000",
"TransferDestinationId": "72a29052-0d99-49ec-a103-3b5ca86b5b4c",
"Title": "Rept\u00E9ri t\u00FAra",
"Bio": "boooob jhkl hjk hjfdsklh sjklfh sjkfh sjklfhdsjlfh djkf hdjklf hjk fldshjkf hdsjkf hdjk fhdsjkf",
"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"
"Created": "0001-01-01T00:00:00",
"Modified": "2025-09-18T12:03:42.0805437Z"
}

View File

@ -0,0 +1,9 @@
{
"Id": "00000000-0000-0000-0000-000000000000",
"TransferDestinationId": "d9bd0565-fea5-4668-9f86-e468a515d5ea",
"Title": "Candlelight tour in the city of Vienna",
"FancyDescription": "kfh dghdfjdjklgh djklgh fjklgdfjklh sjklfh jklshh sjkgh sfjkh slgdf kjhsgjklhg skjl skl",
"CoverImageUrl": "/uploads/tourcovers/d9bd0565-fea5-4668-9f86-e468a515d5ea.jpeg",
"Created": "2025-09-04T10:20:08.4277228Z",
"Modified": "2025-09-04T10:20:08.4277235Z"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View File

@ -11,6 +11,7 @@ namespace TIAMWebApp.Shared.Application.Models
public Guid Id { get; set; }
public Guid TransferDestinationId { get; set; }
public string Title { get; set; }
public string Bio { get; set; }
public string? FancyDescription { get; set; }
public string? CoverImageUrl { get; set; }
public DateTime Created { get; set; }