mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-14 03:02:15 +01:00
move ui and api to seperate packages and add npm actions for them
This commit is contained in:
33
resources/js/packages/ui/src/utils/color.ts
Normal file
33
resources/js/packages/ui/src/utils/color.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import Prando from '@/packages/ui/src/utils/random';
|
||||
|
||||
export const colors = [
|
||||
'#ef5350',
|
||||
'#ec407a',
|
||||
'#ab47bc',
|
||||
'#7e57c2',
|
||||
'#5c6bc0',
|
||||
'#42a5f5',
|
||||
'#29b6f6',
|
||||
'#26c6da',
|
||||
'#26a69a',
|
||||
'#66bb6a',
|
||||
'#9ccc65',
|
||||
'#d4e157',
|
||||
'#ffee58',
|
||||
'#ffca28',
|
||||
'#ffa726',
|
||||
'#ff7043',
|
||||
'#8d6e63',
|
||||
'#bdbdbd',
|
||||
'#78909c',
|
||||
];
|
||||
|
||||
export function getRandomColor() {
|
||||
return colors[Math.floor(Math.random() * colors.length)];
|
||||
}
|
||||
|
||||
export function getRandomColorWithSeed(seed: string) {
|
||||
const pseudoRandom = new Prando(seed);
|
||||
const index = pseudoRandom.nextInt(0, colors.length - 1);
|
||||
return colors[index];
|
||||
}
|
||||
22
resources/js/packages/ui/src/utils/money.ts
Normal file
22
resources/js/packages/ui/src/utils/money.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
function formatMoney(amount: number, currency: string) {
|
||||
return new Intl.NumberFormat('de-DE', {
|
||||
style: 'currency',
|
||||
currency: currency,
|
||||
}).format(amount);
|
||||
}
|
||||
|
||||
export function formatCents(amount: number, currency: string) {
|
||||
return formatMoney(amount / 100, currency);
|
||||
}
|
||||
|
||||
export function getOrganizationCurrencySymbol(currency: string) {
|
||||
return (0)
|
||||
.toLocaleString('de-DE', {
|
||||
style: 'currency',
|
||||
currency: currency,
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
})
|
||||
.replace(/\d/g, '')
|
||||
.trim();
|
||||
}
|
||||
201
resources/js/packages/ui/src/utils/random.ts
Normal file
201
resources/js/packages/ui/src/utils/random.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* This is a hardfork of Prando, a pseudo-random number generator.
|
||||
* @source https://github.com/zeh/prando
|
||||
*/
|
||||
|
||||
export default class Prando {
|
||||
private static readonly MIN: number = -2147483648; // Int32 min
|
||||
private static readonly MAX: number = 2147483647; // Int32 max
|
||||
|
||||
private _seed: number;
|
||||
private _value = NaN;
|
||||
|
||||
// ================================================================================================================
|
||||
// CONSTRUCTOR ----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Generate a new Prando pseudo-random number generator.
|
||||
*
|
||||
* @param seed - A number or string seed that determines which pseudo-random number sequence will be created. Defaults to a random seed based on `Math.random()`.
|
||||
*/
|
||||
constructor(seed?: number | string) {
|
||||
if (typeof seed === 'string') {
|
||||
// String seed
|
||||
this._seed = this.hashCode(seed);
|
||||
} else if (typeof seed === 'number') {
|
||||
// Numeric seed
|
||||
this._seed = this.getSafeSeed(seed);
|
||||
} else {
|
||||
// Pseudo-random seed
|
||||
this._seed = this.getSafeSeed(
|
||||
Prando.MIN +
|
||||
Math.floor((Prando.MAX - Prando.MIN) * Math.random())
|
||||
);
|
||||
}
|
||||
this.reset();
|
||||
}
|
||||
|
||||
// ================================================================================================================
|
||||
// PUBLIC INTERFACE -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random number between a lower (inclusive) and a higher (exclusive) bounds.
|
||||
*
|
||||
* @param min - The minimum number that can be randomly generated.
|
||||
* @param pseudoMax - The maximum number that can be randomly generated (exclusive).
|
||||
* @return The generated pseudo-random number.
|
||||
*/
|
||||
public next(min = 0, pseudoMax = 1): number {
|
||||
this.recalculate();
|
||||
return this.map(this._value, Prando.MIN, Prando.MAX, min, pseudoMax);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random integer number in a range (inclusive).
|
||||
*
|
||||
* @param min - The minimum number that can be randomly generated.
|
||||
* @param max - The maximum number that can be randomly generated.
|
||||
* @return The generated pseudo-random number.
|
||||
*/
|
||||
public nextInt(min = 10, max = 100): number {
|
||||
this.recalculate();
|
||||
return Math.floor(
|
||||
this.map(this._value, Prando.MIN, Prando.MAX, min, max + 1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random string sequence of a particular length from a specific character range.
|
||||
*
|
||||
* Note: keep in mind that creating a random string sequence does not guarantee uniqueness; there is always a
|
||||
* 1 in (char_length^string_length) chance of collision. For real unique string ids, always check for
|
||||
* pre-existing ids, or employ a robust GUID/UUID generator.
|
||||
*
|
||||
* @param length - Length of the string to be generated.
|
||||
* @param chars - Characters that are used when creating the random string. Defaults to all alphanumeric chars (A-Z, a-z, 0-9).
|
||||
* @return The generated string sequence.
|
||||
*/
|
||||
public nextString(
|
||||
length = 16,
|
||||
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
): string {
|
||||
let str = '';
|
||||
while (str.length < length) {
|
||||
str += this.nextChar(chars);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random string of 1 character specific character range.
|
||||
*
|
||||
* @param chars - Characters that are used when creating the random string. Defaults to all alphanumeric chars (A-Z, a-z, 0-9).
|
||||
* @return The generated character.
|
||||
*/
|
||||
public nextChar(
|
||||
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
): string {
|
||||
return chars.substr(this.nextInt(0, chars.length - 1), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks a pseudo-random item from an array. The array is left unmodified.
|
||||
*
|
||||
* Note: keep in mind that while the returned item will be random enough, picking one item from the array at a time
|
||||
* does not guarantee nor imply that a sequence of random non-repeating items will be picked. If you want to
|
||||
* *pick items in a random order* from an array, instead of *pick one random item from an array*, it's best to
|
||||
* apply a *shuffle* transformation to the array instead, then read it linearly.
|
||||
*
|
||||
* @param array - Array of any type containing one or more candidates for random picking.
|
||||
* @return An item from the array.
|
||||
*/
|
||||
public nextArrayItem<T>(array: T[]): T {
|
||||
return array[this.nextInt(0, array.length - 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random boolean.
|
||||
*
|
||||
* @return A value of true or false.
|
||||
*/
|
||||
public nextBoolean(): boolean {
|
||||
this.recalculate();
|
||||
return this._value > 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips ahead in the sequence of numbers that are being generated. This is equivalent to
|
||||
* calling next() a specified number of times, but faster since it doesn't need to map the
|
||||
* new random numbers to a range and return it.
|
||||
*
|
||||
* @param iterations - The number of items to skip ahead.
|
||||
*/
|
||||
public skip(iterations = 1): void {
|
||||
while (iterations-- > 0) {
|
||||
this.recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the pseudo-random number sequence back to its starting seed. Further calls to next()
|
||||
* will then produce the same sequence of numbers it had produced before. This is equivalent to
|
||||
* creating a new Prando instance with the same seed as another Prando instance.
|
||||
*
|
||||
* Example:
|
||||
* let rng = new Prando(12345678);
|
||||
* console.log(rng.next()); // 0.6177754114889017
|
||||
* console.log(rng.next()); // 0.5784605181725837
|
||||
* rng.reset();
|
||||
* console.log(rng.next()); // 0.6177754114889017 again
|
||||
* console.log(rng.next()); // 0.5784605181725837 again
|
||||
*/
|
||||
public reset(): void {
|
||||
this._value = this._seed;
|
||||
}
|
||||
|
||||
// ================================================================================================================
|
||||
// PRIVATE INTERFACE ----------------------------------------------------------------------------------------------
|
||||
|
||||
private recalculate(): void {
|
||||
this._value = this.xorshift(this._value);
|
||||
}
|
||||
|
||||
private xorshift(value: number): number {
|
||||
// Xorshift*32
|
||||
// Based on George Marsaglia's work: http://www.jstatsoft.org/v08/i14/paper
|
||||
value ^= value << 13;
|
||||
value ^= value >> 17;
|
||||
value ^= value << 5;
|
||||
return value;
|
||||
}
|
||||
|
||||
private map(
|
||||
val: number,
|
||||
minFrom: number,
|
||||
maxFrom: number,
|
||||
minTo: number,
|
||||
maxTo: number
|
||||
): number {
|
||||
return (
|
||||
((val - minFrom) / (maxFrom - minFrom)) * (maxTo - minTo) + minTo
|
||||
);
|
||||
}
|
||||
|
||||
private hashCode(str: string): number {
|
||||
let hash = 0;
|
||||
if (str) {
|
||||
const l = str.length;
|
||||
for (let i = 0; i < l; i++) {
|
||||
hash = (hash << 5) - hash + str.charCodeAt(i);
|
||||
hash |= 0;
|
||||
hash = this.xorshift(hash);
|
||||
}
|
||||
}
|
||||
return this.getSafeSeed(hash);
|
||||
}
|
||||
|
||||
private getSafeSeed(seed: number): number {
|
||||
if (seed === 0) return 1;
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
111
resources/js/packages/ui/src/utils/time.ts
Normal file
111
resources/js/packages/ui/src/utils/time.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import dayjs from 'dayjs';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import isToday from 'dayjs/plugin/isToday';
|
||||
import isYesterday from 'dayjs/plugin/isYesterday';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import weekOfYear from 'dayjs/plugin/weekOfYear';
|
||||
import { getUserTimezone, getWeekStart } from '@/utils/useUser';
|
||||
import updateLocale from 'dayjs/plugin/updateLocale';
|
||||
import { computed } from 'vue';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(isToday);
|
||||
dayjs.extend(isYesterday);
|
||||
dayjs.extend(duration);
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(updateLocale);
|
||||
dayjs.extend(weekOfYear);
|
||||
|
||||
export function getDayJsInstance() {
|
||||
dayjs.updateLocale('en', {
|
||||
weekStart: firstDayIndex.value,
|
||||
});
|
||||
return dayjs;
|
||||
}
|
||||
|
||||
export const firstDayIndex = computed(() => {
|
||||
const apiDayOrder = [
|
||||
'sunday',
|
||||
'monday',
|
||||
'tuesday',
|
||||
'wednesday',
|
||||
'thursday',
|
||||
'friday',
|
||||
'saturday',
|
||||
];
|
||||
return apiDayOrder.indexOf(getWeekStart());
|
||||
});
|
||||
|
||||
export function formatHumanReadableDuration(duration: number): string {
|
||||
const dayJsDuration = dayjs.duration(duration, 's');
|
||||
const hours = Math.floor(dayJsDuration.asHours());
|
||||
const minutes = dayJsDuration.minutes();
|
||||
return `${hours}h ${minutes.toString().padStart(2, '0')}min`;
|
||||
}
|
||||
|
||||
export function formatDuration(duration: number): string {
|
||||
const dayJsDuration = dayjs.duration(duration, 's');
|
||||
const hours = Math.floor(dayJsDuration.asHours());
|
||||
const minutes = dayJsDuration.minutes();
|
||||
const seconds = dayJsDuration.seconds();
|
||||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
export function calculateDifference(start: string, end: string | null) {
|
||||
if (end === null) {
|
||||
end = dayjs().utc().format();
|
||||
}
|
||||
return dayjs(end).diff(dayjs(start), 'second');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted time.
|
||||
* @param date - A UTC date time string.
|
||||
*/
|
||||
export function formatTime(date: string) {
|
||||
return dayjs.utc(date).tz(getUserTimezone()).format('HH:mm');
|
||||
}
|
||||
|
||||
export function getLocalizedDayJs(timestamp: string | null) {
|
||||
return dayjs.utc(timestamp).tz(getUserTimezone());
|
||||
}
|
||||
|
||||
export function getLocalizedDateFromTimestamp(timestamp: string) {
|
||||
return getLocalizedDayJs(timestamp).format('YYYY-MM-DD');
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a formatted date.
|
||||
* @param date - date in the format of 'YYYY-MM-DD'
|
||||
*/
|
||||
export function formatDate(date: string): string {
|
||||
return dayjs(date).format('DD.MM.YYYY');
|
||||
}
|
||||
|
||||
export function formatWeek(date: string | null): string {
|
||||
return 'Week ' + getDayJsInstance()(date).week();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a human readable date format.
|
||||
* @param date - date in the format of 'YYYY-MM-DD'
|
||||
*/
|
||||
export function formatHumanReadableDate(date: string) {
|
||||
if (dayjs(date).isToday()) {
|
||||
return 'Today';
|
||||
} else if (dayjs(date).isYesterday()) {
|
||||
return 'Yesterday';
|
||||
}
|
||||
return dayjs(date).fromNow();
|
||||
}
|
||||
|
||||
export function formatStartEnd(start: string, end: string | null) {
|
||||
if (end) {
|
||||
return `${formatTime(start)} - ${formatTime(end)}`;
|
||||
} else {
|
||||
return `${formatTime(start)} - ...`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user