initial commit

This commit is contained in:
2026-07-21 14:14:44 +07:00
commit fa7dbb970d
1359 changed files with 104110 additions and 0 deletions
@@ -0,0 +1,14 @@
namespace Indotalent.ConfigBackEnd.Extensions;
public static class DateTimeExtensions
{
private const string DefaultFormat = "dd MMM yyyy, HH:mm";
public static string ToString(this DateTimeOffset? dateTimeOffset, string format = DefaultFormat)
{
if (!dateTimeOffset.HasValue) return "-";
return dateTimeOffset.Value.ToLocalTime().ToString(format);
}
}
+20
View File
@@ -0,0 +1,20 @@
using System.ComponentModel;
using System.Reflection;
namespace Indotalent.ConfigBackEnd.Extensions;
public static class EnumExtension
{
public static string GetDescription(this Enum value)
{
var field = value.GetType().GetField(value.ToString());
if (field == null)
{
return value.ToString();
}
var attribute = field.GetCustomAttribute<DescriptionAttribute>();
return attribute == null ? value.ToString() : attribute.Description;
}
}
@@ -0,0 +1,86 @@
namespace Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Shared.Models;
using Microsoft.AspNetCore.Http;
using System.Text.Json;
public static class GenericExtensions
{
public static bool IsNullOrEmpty<T>(this IEnumerable<T>? enumerable)
{
return enumerable == null || !enumerable.Any();
}
public static T? ToObject<T>(this string json)
{
if (string.IsNullOrWhiteSpace(json)) return default;
return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
public static string ToJson<T>(this T obj)
{
return JsonSerializer.Serialize(obj);
}
public static TDestination MapTo<TDestination>(this object source)
where TDestination : new()
{
var json = JsonSerializer.Serialize(source);
return JsonSerializer.Deserialize<TDestination>(json) ?? new TDestination();
}
public static string ToCurrency(this decimal value, string culture = "id-ID")
{
return value.ToString("C0", new System.Globalization.CultureInfo(culture));
}
public static bool IsBetween<T>(this T value, T low, T high) where T : IComparable<T>
{
return value.CompareTo(low) >= 0 && value.CompareTo(high) <= 0;
}
public static IResult ToApiResponse<T>(this PagedList<T> result)
{
return Results.Ok(new ApiResponse<List<T>>
{
IsSuccess = true,
StatusCode = 200,
Value = result.Value,
Pagination = new PaginationMetadata
{
Count = result.Count,
Top = result.Top,
Skip = result.Skip
},
ServerTime = DateTime.UtcNow
});
}
public static IResult ToApiResponse<T>(this T? result, string? message = null, int statusCode = 200)
{
if (result == null)
{
return Results.NotFound(new ApiResponse<T>
{
IsSuccess = false,
StatusCode = 404,
Message = message ?? "Data not found",
ServerTime = DateTime.UtcNow
});
}
return Results.Ok(new ApiResponse<T>
{
IsSuccess = true,
StatusCode = statusCode,
Message = message,
Value = result,
Pagination = null,
ServerTime = DateTime.UtcNow
});
}
}
@@ -0,0 +1,63 @@
namespace Indotalent.ConfigBackEnd.Extensions;
using Indotalent.Data.Interfaces;
using Indotalent.Shared.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
public static class IQueryableExtensions
{
public static IQueryable<T> WhereIf<T>(
this IQueryable<T> query,
bool condition,
Expression<Func<T, bool>> predicate)
{
return condition ? query.Where(predicate) : query;
}
public static async Task<PagedList<T>> ToPagedListAsync<T>(
this IQueryable<T> query,
int skip,
int top)
{
top = top <= 0 ? 5 : top;
skip = skip < 0 ? 0 : skip;
var count = await query.CountAsync();
var items = await query
.Skip(skip)
.Take(top)
.ToListAsync();
return new PagedList<T>(items, count, skip, top);
}
public static IQueryable<T> OrderByPropertyName<T>(
this IQueryable<T> query,
string? propertyName,
bool isDescending)
{
if (string.IsNullOrWhiteSpace(propertyName)) return query;
var parameter = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(property, parameter);
var methodName = isDescending ? "OrderByDescending" : "OrderBy";
var resultExpression = Expression.Call(
typeof(Queryable),
methodName,
new Type[] { typeof(T), property.Type },
query.Expression,
Expression.Quote(lambda));
return query.Provider.CreateQuery<T>(resultExpression);
}
public static IQueryable<T> NotDeletedOnly<T>(this IQueryable<T> query)
where T : class, IHasIsDeleted
{
return query.Where(x => !x.IsDeleted);
}
}
@@ -0,0 +1,51 @@
namespace Indotalent.ConfigBackEnd.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
public static class ListExtensions
{
public static void AddIf<T>(this IList<T> list, bool condition, T item)
{
if (condition)
{
list.Add(item);
}
}
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int size)
{
while (source.Any())
{
yield return source.Take(size);
source = source.Skip(size);
}
}
public static void Shuffle<T>(this IList<T> list)
{
var rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (var element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
@@ -0,0 +1,92 @@
namespace Indotalent.ConfigBackEnd.Extensions;
using System.Text.RegularExpressions;
public static class StringExtensions
{
public static string ToShortNameVowel(this string? value, int length = 3)
{
if (string.IsNullOrWhiteSpace(value)) return "GEN";
var vowels = new string(value.Where(c => "AEIOUaeiou".Contains(c)).ToArray());
var baseName = vowels.Length >= length ? vowels : value;
return new string(baseName.Trim().Take(length).ToArray()).ToUpper();
}
public static string ToShortNameConsonant(this string? value, int length = 3)
{
if (string.IsNullOrWhiteSpace(value)) return "GEN";
var consonants = new string(value.Where(c => char.IsLetter(c) && !"AEIOUaeiou".Contains(c)).ToArray());
var baseName = consonants.Length >= length ? consonants : value;
return new string(baseName.Trim().Take(length).ToArray()).ToUpper();
}
public static string ToInitial(this string? value)
{
if (string.IsNullOrWhiteSpace(value)) return "XX";
var words = value.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (words.Length >= 2)
{
var firstInitial = words[0][0];
var secondInitial = words[1][0];
return $"{firstInitial}{secondInitial}".ToUpper();
}
return new string(value.Trim().Take(2).ToArray()).ToUpper();
}
public static bool IsNotNullOrWhiteSpace(this string? value)
{
return !string.IsNullOrWhiteSpace(value);
}
public static string ToTitleCase(this string? value)
{
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
return System.Globalization.CultureInfo.CurrentCulture.TextInfo
.ToTitleCase(value.ToLower().Trim());
}
public static string ToSlug(this string? value)
{
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
var str = value.ToLower().Trim();
str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
str = Regex.Replace(str, @"[\s-]+", " ").Trim();
str = str.Replace(" ", "-");
return str;
}
public static string MaskEmail(this string? email)
{
if (string.IsNullOrWhiteSpace(email) || !email.Contains("@")) return "******";
var parts = email.Split('@');
var name = parts[0];
var domain = parts[1];
if (name.Length <= 2) return $"{name}***@{domain}";
return $"{name[..2]}***{name[^1..]}@{domain}";
}
public static string Truncate(this string? value, int maxLength)
{
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
return value.Length <= maxLength ? value : $"{value[..maxLength]}...";
}
public static string RemoveNonNumeric(this string? value)
{
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
return Regex.Replace(value, "[^0-9]", "");
}
}