434 lines
9.6 KiB
TypeScript
434 lines
9.6 KiB
TypeScript
import Stripe from 'stripe';
|
|
import { BusinessListing, CommercialPropertyListing, Sender, SortByOptions, SortByTypes, User } from './db.model';
|
|
import { State } from './server.model';
|
|
|
|
export interface StatesResult {
|
|
state: string;
|
|
count: number;
|
|
}
|
|
|
|
export interface KeyValue {
|
|
name: string;
|
|
value: string;
|
|
}
|
|
export interface KeyValueAsSortBy {
|
|
name: string;
|
|
value: SortByOptions;
|
|
type?: SortByTypes;
|
|
selectName?: string;
|
|
}
|
|
export interface KeyValueRatio {
|
|
label: string;
|
|
value: number;
|
|
}
|
|
export interface KeyValueStyle {
|
|
name: string;
|
|
value: string;
|
|
oldValue?: string;
|
|
icon: string;
|
|
textColorClass: string;
|
|
}
|
|
export type SelectOption<T = number> = {
|
|
value: T;
|
|
label: string;
|
|
};
|
|
export type ImageType = {
|
|
name: 'propertyPicture' | 'companyLogo' | 'profile';
|
|
upload: string;
|
|
delete: string;
|
|
};
|
|
export type ListingCategory = {
|
|
name: 'business' | 'commercialProperty';
|
|
};
|
|
|
|
export type ListingType = BusinessListing | CommercialPropertyListing;
|
|
|
|
export type ResponseBusinessListingArray = {
|
|
results: BusinessListing[];
|
|
totalCount: number;
|
|
};
|
|
export type ResponseBusinessListing = {
|
|
data: BusinessListing;
|
|
};
|
|
export type ResponseCommercialPropertyListingArray = {
|
|
results: CommercialPropertyListing[];
|
|
totalCount: number;
|
|
};
|
|
export type ResponseCommercialPropertyListing = {
|
|
data: CommercialPropertyListing;
|
|
};
|
|
export type ResponseUsersArray = {
|
|
results: User[];
|
|
totalCount: number;
|
|
};
|
|
export interface ListCriteria {
|
|
start: number;
|
|
length: number;
|
|
page: number;
|
|
types: string[];
|
|
state: string;
|
|
city: GeoResult;
|
|
prompt: string;
|
|
sortBy: SortByOptions;
|
|
searchType: 'exact' | 'radius';
|
|
// radius: '5' | '20' | '50' | '100' | '200' | '300' | '400' | '500';
|
|
radius: number;
|
|
criteriaType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings';
|
|
}
|
|
export interface BusinessListingCriteria extends ListCriteria {
|
|
minPrice: number;
|
|
maxPrice: number;
|
|
minRevenue: number;
|
|
maxRevenue: number;
|
|
minCashFlow: number;
|
|
maxCashFlow: number;
|
|
minNumberEmployees: number;
|
|
maxNumberEmployees: number;
|
|
establishedSince: number;
|
|
establishedUntil: number;
|
|
realEstateChecked: boolean;
|
|
leasedLocation: boolean;
|
|
franchiseResale: boolean;
|
|
title: string;
|
|
brokerName: string;
|
|
email: string;
|
|
criteriaType: 'businessListings';
|
|
}
|
|
export interface CommercialPropertyListingCriteria extends ListCriteria {
|
|
minPrice: number;
|
|
maxPrice: number;
|
|
title: string;
|
|
criteriaType: 'commercialPropertyListings';
|
|
}
|
|
export interface UserListingCriteria extends ListCriteria {
|
|
brokerName: string;
|
|
companyName: string;
|
|
counties: string[];
|
|
criteriaType: 'brokerListings';
|
|
}
|
|
|
|
export interface KeycloakUser {
|
|
id: string;
|
|
createdTimestamp?: number;
|
|
username?: string;
|
|
enabled?: boolean;
|
|
totp?: boolean;
|
|
emailVerified?: boolean;
|
|
firstName: string;
|
|
lastName: string;
|
|
email: string;
|
|
disableableCredentialTypes?: any[];
|
|
requiredActions?: any[];
|
|
notBefore?: number;
|
|
access?: Access;
|
|
attributes?: Attributes;
|
|
}
|
|
export interface JwtUser {
|
|
email: string;
|
|
role: string;
|
|
uid: string;
|
|
}
|
|
interface Attributes {
|
|
[key: string]: any;
|
|
priceID: any;
|
|
}
|
|
export interface Access {
|
|
manageGroupMembership: boolean;
|
|
view: boolean;
|
|
mapRoles: boolean;
|
|
impersonate: boolean;
|
|
manage: boolean;
|
|
}
|
|
export interface Subscription {
|
|
id: string;
|
|
userId: string;
|
|
level: string;
|
|
start: Date;
|
|
modified: Date;
|
|
end: Date;
|
|
status: string;
|
|
invoices: Array<Invoice>;
|
|
}
|
|
export interface Invoice {
|
|
id: string;
|
|
date: Date;
|
|
price: number;
|
|
}
|
|
export interface JwtToken {
|
|
exp: number;
|
|
iat: number;
|
|
auth_time: number;
|
|
jti: string;
|
|
iss: string;
|
|
aud: string;
|
|
sub: string;
|
|
typ: string;
|
|
azp: string;
|
|
nonce: string;
|
|
session_state: string;
|
|
acr: string;
|
|
realm_access: Realmaccess;
|
|
resource_access: Resourceaccess;
|
|
scope: string;
|
|
sid: string;
|
|
email_verified: boolean;
|
|
name: string;
|
|
preferred_username: string;
|
|
given_name: string;
|
|
family_name: string;
|
|
email: string;
|
|
user_id: string;
|
|
price_id: string;
|
|
}
|
|
export interface JwtPayload {
|
|
sub: string;
|
|
preferred_username: string;
|
|
realm_access?: {
|
|
roles?: string[];
|
|
};
|
|
[key: string]: any; // für andere optionale Felder im JWT-Payload
|
|
}
|
|
interface Resourceaccess {
|
|
account: Realmaccess;
|
|
}
|
|
interface Realmaccess {
|
|
roles: string[];
|
|
}
|
|
export interface PageEvent {
|
|
first: number;
|
|
rows: number;
|
|
page: number;
|
|
pageCount: number;
|
|
}
|
|
export interface AutoCompleteCompleteEvent {
|
|
originalEvent: Event;
|
|
query: string;
|
|
}
|
|
export interface MailInfo {
|
|
sender: Sender;
|
|
email: string;
|
|
url: string;
|
|
listing?: BusinessListing;
|
|
}
|
|
// export interface Sender {
|
|
// name?: string;
|
|
// email?: string;
|
|
// phoneNumber?: string;
|
|
// state?: string;
|
|
// comments?: string;
|
|
// }
|
|
export interface ImageProperty {
|
|
id: string;
|
|
code: string;
|
|
name: string;
|
|
}
|
|
export interface ErrorResponse {
|
|
fields?: FieldError[];
|
|
general?: string[];
|
|
}
|
|
export interface FieldError {
|
|
fieldname: string;
|
|
message: string;
|
|
}
|
|
export interface UploadParams {
|
|
type: 'uploadPropertyPicture' | 'uploadCompanyLogo' | 'uploadProfile';
|
|
imagePath: string;
|
|
serialId?: number;
|
|
}
|
|
export interface GeoResult {
|
|
id: number;
|
|
name: string;
|
|
street?: string;
|
|
housenumber?: string;
|
|
county?: string;
|
|
zipCode?: number;
|
|
state: string;
|
|
latitude: number;
|
|
longitude: number;
|
|
}
|
|
interface CityResult {
|
|
id: number;
|
|
type: 'city';
|
|
content: GeoResult;
|
|
}
|
|
|
|
interface StateResult {
|
|
id: number;
|
|
type: 'state';
|
|
content: State;
|
|
}
|
|
export type CityAndStateResult = CityResult | StateResult;
|
|
export interface CountyResult {
|
|
id: number;
|
|
name: string;
|
|
state: string;
|
|
state_code: string;
|
|
}
|
|
export interface LogMessage {
|
|
severity: 'error' | 'info';
|
|
text: string;
|
|
}
|
|
export interface ModalResult {
|
|
accepted: boolean;
|
|
criteria?: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
|
}
|
|
export interface Checkout {
|
|
priceId: string;
|
|
email: string;
|
|
name: string;
|
|
}
|
|
export type UserRole = 'admin' | 'pro' | 'guest' | null;
|
|
export interface FirebaseUserInfo {
|
|
uid: string;
|
|
email: string | null;
|
|
displayName: string | null;
|
|
photoURL: string | null;
|
|
phoneNumber: string | null;
|
|
disabled: boolean;
|
|
emailVerified: boolean;
|
|
role: UserRole;
|
|
creationTime?: string;
|
|
lastSignInTime?: string;
|
|
customClaims?: Record<string, any>;
|
|
}
|
|
|
|
export interface UsersResponse {
|
|
users: FirebaseUserInfo[];
|
|
totalCount: number;
|
|
pageToken?: string;
|
|
}
|
|
export function isEmpty(value: any): boolean {
|
|
// Check for undefined or null
|
|
if (value === undefined || value === null) {
|
|
return true;
|
|
}
|
|
|
|
// Check for empty string or string with only whitespace
|
|
if (typeof value === 'string') {
|
|
return value.trim().length === 0;
|
|
}
|
|
|
|
// Check for number and NaN
|
|
if (typeof value === 'number') {
|
|
return isNaN(value);
|
|
}
|
|
|
|
// If it's not a string or number, it's not considered empty by this function
|
|
return false;
|
|
}
|
|
export function emailToDirName(email: string): string {
|
|
if (email === undefined || email === null) {
|
|
return null;
|
|
}
|
|
// Entferne ungültige Zeichen und ersetze sie durch Unterstriche
|
|
const sanitizedEmail = email.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
|
|
// Entferne führende und nachfolgende Unterstriche
|
|
const trimmedEmail = sanitizedEmail.replace(/^_+|_+$/g, '');
|
|
|
|
// Ersetze mehrfache aufeinanderfolgende Unterstriche durch einen einzelnen Unterstrich
|
|
const normalizedEmail = trimmedEmail.replace(/_+/g, '_');
|
|
|
|
return normalizedEmail;
|
|
}
|
|
export const LISTINGS_PER_PAGE = 12;
|
|
export interface ValidationMessage {
|
|
field: string;
|
|
message: string;
|
|
}
|
|
export function createDefaultUser(email: string, firstname: string, lastname: string, subscriptionPlan: 'professional' | 'broker'): User {
|
|
return {
|
|
id: undefined,
|
|
email,
|
|
firstname,
|
|
lastname,
|
|
phoneNumber: null,
|
|
description: null,
|
|
companyName: null,
|
|
companyOverview: null,
|
|
companyWebsite: null,
|
|
location: null,
|
|
offeredServices: null,
|
|
areasServed: [],
|
|
hasProfile: false,
|
|
hasCompanyLogo: false,
|
|
licensedIn: [],
|
|
gender: null,
|
|
customerType: 'buyer',
|
|
customerSubType: null,
|
|
created: new Date(),
|
|
updated: new Date(),
|
|
subscriptionId: null,
|
|
subscriptionPlan: subscriptionPlan,
|
|
};
|
|
}
|
|
export function createDefaultCommercialPropertyListing(): CommercialPropertyListing {
|
|
return {
|
|
id: undefined,
|
|
serialId: undefined,
|
|
email: null,
|
|
type: null,
|
|
title: null,
|
|
description: null,
|
|
location: null,
|
|
price: null,
|
|
favoritesForUser: [],
|
|
draft: false,
|
|
imageOrder: [],
|
|
imagePath: null,
|
|
created: null,
|
|
updated: null,
|
|
listingsCategory: 'commercialProperty',
|
|
};
|
|
}
|
|
export function createDefaultBusinessListing(): BusinessListing {
|
|
return {
|
|
id: undefined,
|
|
email: null,
|
|
type: null,
|
|
title: null,
|
|
description: null,
|
|
location: null,
|
|
price: null,
|
|
favoritesForUser: [],
|
|
draft: false,
|
|
realEstateIncluded: false,
|
|
leasedLocation: false,
|
|
franchiseResale: false,
|
|
salesRevenue: null,
|
|
cashFlow: null,
|
|
supportAndTraining: null,
|
|
employees: null,
|
|
established: null,
|
|
internalListingNumber: null,
|
|
reasonForSale: null,
|
|
brokerLicencing: null,
|
|
internals: null,
|
|
created: null,
|
|
updated: null,
|
|
listingsCategory: 'business',
|
|
};
|
|
}
|
|
export type StripeSubscription = Stripe.Subscription;
|
|
export type StripeUser = Stripe.Customer;
|
|
export type IpInfo = {
|
|
ip: string;
|
|
city: string;
|
|
region: string;
|
|
country: string;
|
|
loc: string; // Coordinates in "latitude,longitude" format
|
|
org: string;
|
|
postal: string;
|
|
timezone: string;
|
|
};
|
|
export interface CombinedUser {
|
|
keycloakUser?: KeycloakUser;
|
|
appUser?: User;
|
|
stripeUser?: StripeUser;
|
|
stripeSubscription?: StripeSubscription;
|
|
}
|
|
export interface RealIpInfo {
|
|
ip: string;
|
|
countryCode?: string;
|
|
}
|