wedance-shared 1.0.43 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/other.d.ts +0 -3
- package/package.json +6 -3
- package/.prettierrc.js +0 -8
- package/eslint.config.mjs +0 -36
- package/index.ts +0 -1
- package/script/incrementVersion.sh +0 -73
- package/src/index.ts +0 -2
- package/src/types/analytics.ts +0 -27
- package/src/types/city.ts +0 -79
- package/src/types/event.ts +0 -178
- package/src/types/festivals/festival.ts +0 -81
- package/src/types/festivals/index.ts +0 -2
- package/src/types/festivals/user.ts +0 -44
- package/src/types/index.ts +0 -11
- package/src/types/organizer.ts +0 -78
- package/src/types/other.ts +0 -27
- package/src/types/ticket.ts +0 -188
- package/src/types/user.ts +0 -52
- package/src/utils/date.ts +0 -111
- package/tsconfig.json +0 -19
package/dist/types/other.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wedance-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.45",
|
|
4
4
|
"description": "This repository contains shared TypeScript types and interfaces used across multiple WeDance applications:",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
7
10
|
"exports": {
|
|
8
11
|
".": {
|
|
9
12
|
"types": "./dist/index.d.ts",
|
|
@@ -22,10 +25,10 @@
|
|
|
22
25
|
"check-format": "prettier --check \"src/**/*.ts\"",
|
|
23
26
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
24
27
|
"clean": "rm -rf dist",
|
|
25
|
-
"version:patch": "script/incrementVersion.sh",
|
|
28
|
+
"version:patch": "script/incrementVersion.sh patch",
|
|
26
29
|
"version:minor": "script/incrementVersion.sh minor",
|
|
27
30
|
"version:major": "script/incrementVersion.sh major",
|
|
28
|
-
"
|
|
31
|
+
"publish": "npm run build && npm run \"version:patch\" && git add . && git commit -m \"chore: update version\" && git push && npm publish --access public "
|
|
29
32
|
},
|
|
30
33
|
"keywords": [],
|
|
31
34
|
"author": "",
|
package/.prettierrc.js
DELETED
package/eslint.config.mjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import eslint from '@eslint/js'
|
|
2
|
-
import tseslint from '@typescript-eslint/eslint-plugin'
|
|
3
|
-
import typescript from '@typescript-eslint/parser'
|
|
4
|
-
import prettier from 'eslint-config-prettier'
|
|
5
|
-
import eslintPluginPrettier from 'eslint-plugin-prettier'
|
|
6
|
-
|
|
7
|
-
export default [
|
|
8
|
-
eslint.configs.recommended,
|
|
9
|
-
{
|
|
10
|
-
files: ['src/**/*.ts'],
|
|
11
|
-
languageOptions: {
|
|
12
|
-
parser: typescript,
|
|
13
|
-
parserOptions: {
|
|
14
|
-
project: './tsconfig.json',
|
|
15
|
-
ecmaVersion: 2020,
|
|
16
|
-
sourceType: 'module'
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
plugins: {
|
|
20
|
-
'@typescript-eslint': tseslint,
|
|
21
|
-
prettier: eslintPluginPrettier
|
|
22
|
-
},
|
|
23
|
-
rules: {
|
|
24
|
-
'prettier/prettier': 'warning',
|
|
25
|
-
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
26
|
-
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
27
|
-
'@typescript-eslint/no-explicit-any': 'error',
|
|
28
|
-
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
29
|
-
'no-console': ['warn', { allow: ['warn', 'error'] }]
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
ignores: ['dist/**', 'node_modules/**', '*.js']
|
|
34
|
-
},
|
|
35
|
-
prettier
|
|
36
|
-
]
|
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./src";
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# This script increments the version in package.json
|
|
4
|
-
# Usage: ./incrementVersion.sh [major|minor|patch]
|
|
5
|
-
# Default is patch if no argument is provided
|
|
6
|
-
|
|
7
|
-
# Function to display usage information
|
|
8
|
-
show_usage() {
|
|
9
|
-
echo "Usage: $0 [major|minor|patch]"
|
|
10
|
-
echo "Default is patch if no argument is provided"
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
# Check if package.json exists
|
|
14
|
-
if [ ! -f "package.json" ]; then
|
|
15
|
-
echo "Error: package.json not found in current directory"
|
|
16
|
-
exit 1
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
# Determine which version part to increment
|
|
20
|
-
VERSION_PART=${1:-patch}
|
|
21
|
-
|
|
22
|
-
if [[ ! $VERSION_PART =~ ^(major|minor|patch)$ ]]; then
|
|
23
|
-
echo "Error: Invalid version part. Must be one of: major, minor, patch"
|
|
24
|
-
show_usage
|
|
25
|
-
exit 1
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
# Get current version from package.json
|
|
29
|
-
CURRENT_VERSION=$(grep -o '"version": "[^"]*' package.json | cut -d'"' -f4)
|
|
30
|
-
|
|
31
|
-
if [ -z "$CURRENT_VERSION" ]; then
|
|
32
|
-
echo "Error: Unable to find version in package.json"
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
echo "Current version: $CURRENT_VERSION"
|
|
37
|
-
|
|
38
|
-
# Split version into components
|
|
39
|
-
IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION"
|
|
40
|
-
MAJOR=${VERSION_PARTS[0]}
|
|
41
|
-
MINOR=${VERSION_PARTS[1]}
|
|
42
|
-
PATCH=${VERSION_PARTS[2]}
|
|
43
|
-
|
|
44
|
-
# Increment appropriate version part
|
|
45
|
-
case $VERSION_PART in
|
|
46
|
-
major)
|
|
47
|
-
MAJOR=$((MAJOR + 1))
|
|
48
|
-
MINOR=0
|
|
49
|
-
PATCH=0
|
|
50
|
-
;;
|
|
51
|
-
minor)
|
|
52
|
-
MINOR=$((MINOR + 1))
|
|
53
|
-
PATCH=0
|
|
54
|
-
;;
|
|
55
|
-
patch)
|
|
56
|
-
PATCH=$((PATCH + 1))
|
|
57
|
-
;;
|
|
58
|
-
esac
|
|
59
|
-
|
|
60
|
-
# Construct new version
|
|
61
|
-
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
|
|
62
|
-
echo "New version: $NEW_VERSION"
|
|
63
|
-
|
|
64
|
-
# Update version in package.json
|
|
65
|
-
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
66
|
-
# macOS requires a slightly different sed syntax
|
|
67
|
-
sed -i '' "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$NEW_VERSION\"/" package.json
|
|
68
|
-
else
|
|
69
|
-
# Linux version
|
|
70
|
-
sed -i "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$NEW_VERSION\"/" package.json
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
echo "Updated package.json version to $NEW_VERSION"
|
package/src/index.ts
DELETED
package/src/types/analytics.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Timestamp } from "firebase/firestore";
|
|
2
|
-
|
|
3
|
-
export type GoogleAnalyticsResponse = {
|
|
4
|
-
dimensionHeaders: { name: string }[];
|
|
5
|
-
metricHeaders: { name: string; type: string }[];
|
|
6
|
-
rows: {
|
|
7
|
-
dimensionValues: { value: string }[];
|
|
8
|
-
metricValues: { value: string }[];
|
|
9
|
-
}[];
|
|
10
|
-
rowCount: number;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type EventAnalyticsMetrics = {
|
|
14
|
-
eventCount: string;
|
|
15
|
-
totalUsers: string;
|
|
16
|
-
eventId: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type DailyAnalyticsReport = {
|
|
20
|
-
createdAt: Timestamp;
|
|
21
|
-
data: EventAnalyticsMetrics[];
|
|
22
|
-
reportDate: string;
|
|
23
|
-
dateRange: {
|
|
24
|
-
endDate: string;
|
|
25
|
-
startDate: string;
|
|
26
|
-
};
|
|
27
|
-
};
|
package/src/types/city.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
type CityData =
|
|
2
|
-
| {
|
|
3
|
-
city: "helsinki";
|
|
4
|
-
country: "fi";
|
|
5
|
-
coordinates: [60.1695, 24.9354];
|
|
6
|
-
}
|
|
7
|
-
| {
|
|
8
|
-
city: "tampere";
|
|
9
|
-
country: "fi";
|
|
10
|
-
coordinates: [61.4978, 23.761];
|
|
11
|
-
}
|
|
12
|
-
| {
|
|
13
|
-
city: "oulu";
|
|
14
|
-
country: "fi";
|
|
15
|
-
coordinates: [65.012, 25.468];
|
|
16
|
-
};
|
|
17
|
-
// | {
|
|
18
|
-
// city: "oslo";
|
|
19
|
-
// country: "no";
|
|
20
|
-
// coordinates: [59.9139, 10.7522];
|
|
21
|
-
// }
|
|
22
|
-
// | {
|
|
23
|
-
// city: "tallinn";
|
|
24
|
-
// country: "ee";
|
|
25
|
-
// coordinates: [59.437, 24.7536];
|
|
26
|
-
// }
|
|
27
|
-
// | {
|
|
28
|
-
// city: "copenhagen";
|
|
29
|
-
// country: "dk";
|
|
30
|
-
// coordinates: [55.6761, 12.5683];
|
|
31
|
-
// };
|
|
32
|
-
|
|
33
|
-
export const LIST_CITIES: CityData[] = [
|
|
34
|
-
{
|
|
35
|
-
city: "helsinki",
|
|
36
|
-
country: "fi",
|
|
37
|
-
coordinates: [60.1695, 24.9354]
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
city: "tampere",
|
|
41
|
-
country: "fi",
|
|
42
|
-
coordinates: [61.4978, 23.761]
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
city: "oulu",
|
|
46
|
-
country: "fi",
|
|
47
|
-
coordinates: [65.012, 25.468]
|
|
48
|
-
}
|
|
49
|
-
// {
|
|
50
|
-
// city: "oslo",
|
|
51
|
-
// country: "no",
|
|
52
|
-
// coordinates: [59.9139, 10.7522]
|
|
53
|
-
// },
|
|
54
|
-
// {
|
|
55
|
-
// city: 'stockholm',
|
|
56
|
-
// country: 'se',
|
|
57
|
-
// },
|
|
58
|
-
// {
|
|
59
|
-
// city: "tallinn",
|
|
60
|
-
// country: "ee",
|
|
61
|
-
// coordinates: [59.437, 24.7536]
|
|
62
|
-
// },
|
|
63
|
-
// {
|
|
64
|
-
// city: "copenhagen",
|
|
65
|
-
// country: "dk",
|
|
66
|
-
// coordinates: [55.6761, 12.5683]
|
|
67
|
-
// },
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
export type City = CityData;
|
|
71
|
-
export type CityName = CityData["city"];
|
|
72
|
-
export type CountryCode = CityData["country"];
|
|
73
|
-
|
|
74
|
-
export enum Timezone {
|
|
75
|
-
FINLAND = "Europe/Helsinki",
|
|
76
|
-
DENMARK = "Europe/Copenhagen",
|
|
77
|
-
SWEDEN = "Europe/Stockholm",
|
|
78
|
-
NORWAY = "Europe/Oslo"
|
|
79
|
-
}
|
package/src/types/event.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { Timestamp } from "firebase/firestore";
|
|
2
|
-
import { City } from "./city.js";
|
|
3
|
-
import { OrganizerName } from "./organizer.js";
|
|
4
|
-
import { EventTicket } from "./ticket.js";
|
|
5
|
-
import { UserBadge } from "./user.js";
|
|
6
|
-
|
|
7
|
-
export type DanceTag =
|
|
8
|
-
| "salsa"
|
|
9
|
-
| "kizomba"
|
|
10
|
-
| "bachata"
|
|
11
|
-
| "zouk"
|
|
12
|
-
| "tango"
|
|
13
|
-
| "heels"
|
|
14
|
-
| "hiphop"
|
|
15
|
-
| "reggaeton"
|
|
16
|
-
| "other";
|
|
17
|
-
|
|
18
|
-
export type Organizer = {
|
|
19
|
-
name: OrganizerName;
|
|
20
|
-
email?: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type Links = {
|
|
24
|
-
paymentLink?: string;
|
|
25
|
-
instagram?: string;
|
|
26
|
-
facebook?: string;
|
|
27
|
-
website?: string;
|
|
28
|
-
other?: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type Location = {
|
|
32
|
-
name: string;
|
|
33
|
-
address?: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type EventStatus = "published" | "cancelled" | "unpublished";
|
|
37
|
-
|
|
38
|
-
export type ImageData = {
|
|
39
|
-
url: string;
|
|
40
|
-
alt?: string;
|
|
41
|
-
blurhash?: string;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* This is the type of the data we get from the server
|
|
46
|
-
* */
|
|
47
|
-
export type EventData = {
|
|
48
|
-
id: string;
|
|
49
|
-
// Id from an event added by a partner.
|
|
50
|
-
externalId: string | null | undefined;
|
|
51
|
-
title: string;
|
|
52
|
-
// Date in iso format
|
|
53
|
-
from: string;
|
|
54
|
-
// Date in iso format
|
|
55
|
-
until: string;
|
|
56
|
-
price: number;
|
|
57
|
-
priceProvided: boolean;
|
|
58
|
-
// Deprecated. Use organizerId instead.
|
|
59
|
-
organizer: Organizer;
|
|
60
|
-
organizerId: string;
|
|
61
|
-
description: string;
|
|
62
|
-
location: Location;
|
|
63
|
-
// In hours
|
|
64
|
-
duration?: number;
|
|
65
|
-
tags: DanceTag[];
|
|
66
|
-
links: Links;
|
|
67
|
-
/**
|
|
68
|
-
* Events have international artists
|
|
69
|
-
*/
|
|
70
|
-
isInternational: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* Is event private? @deprecated
|
|
73
|
-
*/
|
|
74
|
-
isPrivate?: boolean;
|
|
75
|
-
hasSeveralPrices?: boolean;
|
|
76
|
-
createdAt: string;
|
|
77
|
-
lastUpdated?: string;
|
|
78
|
-
publishedSchedule?: boolean;
|
|
79
|
-
schedule: EventSchedule | null;
|
|
80
|
-
// Email of the user who added the event
|
|
81
|
-
addedBy: string;
|
|
82
|
-
updatedBy: string;
|
|
83
|
-
paymentLink: string | null;
|
|
84
|
-
status: EventStatus | null;
|
|
85
|
-
city: City;
|
|
86
|
-
isFestival: boolean | null;
|
|
87
|
-
going: UserBadge[] | null;
|
|
88
|
-
interested: UserBadge[] | null;
|
|
89
|
-
imageData: ImageData;
|
|
90
|
-
eventType: EventType;
|
|
91
|
-
eventTickets?: EventTicket[] | null;
|
|
92
|
-
lineup?: LineUpArtist[] | null;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Workshop: Only workshop
|
|
97
|
-
* Social: Only social and possible pre-party class
|
|
98
|
-
* Workshop-and-social: Workshop and social when more than one workshop.
|
|
99
|
-
*/
|
|
100
|
-
export type EventType = "workshop" | "social" | "workshop-and-social";
|
|
101
|
-
|
|
102
|
-
export type EventCellType = "workshop" | "social" | "break" | "other";
|
|
103
|
-
|
|
104
|
-
export type ScheduleItem = {
|
|
105
|
-
id: string;
|
|
106
|
-
headline: string;
|
|
107
|
-
subheader: string | null;
|
|
108
|
-
from: string;
|
|
109
|
-
until: string;
|
|
110
|
-
type: EventCellType;
|
|
111
|
-
level: string | null;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export type EventSchedule = Record<string, ScheduleItem[]>;
|
|
115
|
-
|
|
116
|
-
export type LineUpArtist = {
|
|
117
|
-
id: string;
|
|
118
|
-
name: string;
|
|
119
|
-
description: string;
|
|
120
|
-
image: string;
|
|
121
|
-
imageUrl: string;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
export type Featured = {
|
|
125
|
-
/**
|
|
126
|
-
* ID of the promotion
|
|
127
|
-
*/
|
|
128
|
-
id: string;
|
|
129
|
-
/**
|
|
130
|
-
* ID of the event being promoted
|
|
131
|
-
*/
|
|
132
|
-
eventId: string;
|
|
133
|
-
/**
|
|
134
|
-
* Cities where this promotion should be shown
|
|
135
|
-
*/
|
|
136
|
-
cities: City["city"][];
|
|
137
|
-
/**
|
|
138
|
-
* Priority level for displaying multiple featured events (higher = more prominent)
|
|
139
|
-
*/
|
|
140
|
-
priority: number;
|
|
141
|
-
/**
|
|
142
|
-
* Optional custom promotion message
|
|
143
|
-
*/
|
|
144
|
-
promotionalText?: string;
|
|
145
|
-
/**
|
|
146
|
-
* Who created this promotion
|
|
147
|
-
*/
|
|
148
|
-
createdBy: string;
|
|
149
|
-
/**
|
|
150
|
-
* When this promotion was created (ISO date string)
|
|
151
|
-
*/
|
|
152
|
-
createdAt: Timestamp;
|
|
153
|
-
updatedAt: Timestamp;
|
|
154
|
-
/**
|
|
155
|
-
* Whether the promotion is currently active @deprecated
|
|
156
|
-
*/
|
|
157
|
-
isActive: boolean;
|
|
158
|
-
/**
|
|
159
|
-
* Status of the promotion
|
|
160
|
-
*/
|
|
161
|
-
status: PromotionStatus;
|
|
162
|
-
/**
|
|
163
|
-
* Date range of the promotion
|
|
164
|
-
*/
|
|
165
|
-
dateRange: {
|
|
166
|
-
startDate: Timestamp;
|
|
167
|
-
endDate: Timestamp;
|
|
168
|
-
};
|
|
169
|
-
organizerId: string;
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
export type PromotionStatus =
|
|
173
|
-
| "draft" // Initial state when promotion is created
|
|
174
|
-
| "pending_payment" // Initial state when checkout is created but not paid
|
|
175
|
-
| "payment_failed" // Payment failed
|
|
176
|
-
| "scheduled" // Payment completed but start date is in the future
|
|
177
|
-
| "paused" // User manually paused the promotion
|
|
178
|
-
| "cancelled"; // User/admin cancelled
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Timestamp } from "firebase/firestore";
|
|
2
|
-
import { Links } from "../event.js";
|
|
3
|
-
import { EventTicket } from "../ticket.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* This is the type of the data we get from the server
|
|
7
|
-
* */
|
|
8
|
-
export type FestivalData = {
|
|
9
|
-
id: string;
|
|
10
|
-
title: string;
|
|
11
|
-
from: Timestamp;
|
|
12
|
-
until: Timestamp;
|
|
13
|
-
organizerId: string[];
|
|
14
|
-
description: string;
|
|
15
|
-
location: FestivalLocation[];
|
|
16
|
-
|
|
17
|
-
genre?: FestivalGenre[]; // ["salsa", "bachata"]
|
|
18
|
-
tags?: string[]; // Helps with filtering (e.g., ["music", "art", "food"])
|
|
19
|
-
|
|
20
|
-
imageData: FestivalImageData[];
|
|
21
|
-
|
|
22
|
-
priceRange?: { min: number; max: number; currency: string };
|
|
23
|
-
|
|
24
|
-
createdAt: Timestamp;
|
|
25
|
-
updatedAt: Timestamp;
|
|
26
|
-
|
|
27
|
-
createdBy: string;
|
|
28
|
-
updatedBy: string;
|
|
29
|
-
|
|
30
|
-
links: Links;
|
|
31
|
-
|
|
32
|
-
isFree: boolean;
|
|
33
|
-
|
|
34
|
-
artists: FestivalArtist[];
|
|
35
|
-
tickets?: EventTicket[];
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
type FestivalGenre = "salsa" | "bachata" | "kizomba" | "zouk";
|
|
39
|
-
|
|
40
|
-
type FestivalImageData = {
|
|
41
|
-
url: string;
|
|
42
|
-
alt?: string;
|
|
43
|
-
blurhash?: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export type FestivalLocation = {
|
|
47
|
-
city: string; // e.g., "Stockholm"
|
|
48
|
-
countryCode: string; // ISO 3166-1 (e.g., "SE" for Sweden)
|
|
49
|
-
country: string;
|
|
50
|
-
address?: string; // Optional detailed address (e.g., "Arenavägen 75")
|
|
51
|
-
venue?: string; // Optional (e.g., "Avicii Arena")
|
|
52
|
-
geoLocation?: { lat: number; lng: number }; // For maps
|
|
53
|
-
timeZone: string; // e.g., "Europe/Stockholm"
|
|
54
|
-
region: Region[]; // e.g., "Nordics", "Baltics"
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export type FestivalArtist = {
|
|
58
|
-
id: string;
|
|
59
|
-
name: string;
|
|
60
|
-
image: string;
|
|
61
|
-
imageUrl: string;
|
|
62
|
-
role: FestivalArtistRole;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export type FestivalArtistRole =
|
|
66
|
-
| "dj"
|
|
67
|
-
| "dancer"
|
|
68
|
-
| "mc"
|
|
69
|
-
| "guest-dancer"
|
|
70
|
-
| "organizer"
|
|
71
|
-
| "media";
|
|
72
|
-
|
|
73
|
-
export type Region =
|
|
74
|
-
| "Nordics"
|
|
75
|
-
| "Baltics"
|
|
76
|
-
| "Western Europe"
|
|
77
|
-
| "Eastern Europe"
|
|
78
|
-
| "Southern Europe"
|
|
79
|
-
| "Central Europe"
|
|
80
|
-
| "Asia"
|
|
81
|
-
| "Africa";
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Timestamp } from "firebase/firestore";
|
|
2
|
-
import { Role } from "../user.js";
|
|
3
|
-
|
|
4
|
-
export type FestivalUser = {
|
|
5
|
-
id: string;
|
|
6
|
-
email: string;
|
|
7
|
-
displayName: string;
|
|
8
|
-
profilePicture?: string;
|
|
9
|
-
favoriteFestivals: string[];
|
|
10
|
-
goingFestivals: string[];
|
|
11
|
-
role: Role;
|
|
12
|
-
|
|
13
|
-
// Location details
|
|
14
|
-
location: {
|
|
15
|
-
city: string;
|
|
16
|
-
country: string;
|
|
17
|
-
countryCode: string;
|
|
18
|
-
coordinates: {
|
|
19
|
-
latitude: number;
|
|
20
|
-
longitude: number;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
createdAt: Timestamp;
|
|
25
|
-
lastUpdated: Timestamp;
|
|
26
|
-
lastConnected: Timestamp;
|
|
27
|
-
|
|
28
|
-
fcmTokens: string[];
|
|
29
|
-
appVersion: string;
|
|
30
|
-
deviceModel: string;
|
|
31
|
-
platform: string;
|
|
32
|
-
emailVerified: boolean;
|
|
33
|
-
stripeId?: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export interface UserAttachment {
|
|
37
|
-
id: string; // Firestore document ID
|
|
38
|
-
userId: string;
|
|
39
|
-
name: string;
|
|
40
|
-
eventId: string; // Optional if not always tied to an event
|
|
41
|
-
url: string;
|
|
42
|
-
uploadedAt: Timestamp; // Or Date, depending on usage
|
|
43
|
-
type: "image" | "pdf";
|
|
44
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Re-export all types from individual files
|
|
2
|
-
export * from "./event.js";
|
|
3
|
-
export * from "./ticket.js";
|
|
4
|
-
export * from "./city.js";
|
|
5
|
-
export * from "./organizer.js";
|
|
6
|
-
export * from "./user.js";
|
|
7
|
-
export * from "./other.js";
|
|
8
|
-
export * from "./analytics.js";
|
|
9
|
-
|
|
10
|
-
// Re-export from subdirectories
|
|
11
|
-
export * from "./festivals/index.js";
|
package/src/types/organizer.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { City } from "./city.js";
|
|
2
|
-
|
|
3
|
-
export type OrganizerName =
|
|
4
|
-
// HELSINKI
|
|
5
|
-
| "SOB Productions"
|
|
6
|
-
| "Helsinki SBK"
|
|
7
|
-
| "Avec Dance Club"
|
|
8
|
-
| "Still Dancing"
|
|
9
|
-
| "Tanssikoulu SalsaLatina"
|
|
10
|
-
| "Helsinki Salsa Academy"
|
|
11
|
-
| "BabaGen"
|
|
12
|
-
| "Bachata Studio"
|
|
13
|
-
| "Tanssikoulu BailaBaila"
|
|
14
|
-
| "Petra & Otso"
|
|
15
|
-
| "Bachata Helsinki"
|
|
16
|
-
| "Anton Kargaltsev"
|
|
17
|
-
| "Salsa Borealis"
|
|
18
|
-
| "Helsinki Dance Central"
|
|
19
|
-
| "Urbankiz Helsinki"
|
|
20
|
-
| "S-Dance"
|
|
21
|
-
| "Helsinki Kizomba Studio"
|
|
22
|
-
| "idance Helsinki"
|
|
23
|
-
| "Dance Social"
|
|
24
|
-
| "Tinku Latin Flavours"
|
|
25
|
-
| "Latin Garden Helsinki"
|
|
26
|
-
|
|
27
|
-
// TAMPERE
|
|
28
|
-
| "Tampere Social Dancing"
|
|
29
|
-
| "Azúcar"
|
|
30
|
-
| "Kizomba Social Tampere"
|
|
31
|
-
| "KizLab Tampere"
|
|
32
|
-
|
|
33
|
-
// OULU
|
|
34
|
-
| "Bachata & Kizomba Oulu"
|
|
35
|
-
| "SALSA Klubi"
|
|
36
|
-
| "Tanssikoulu Vamos"
|
|
37
|
-
| "Feels Oulu"
|
|
38
|
-
| "Bachata Sensual Lovers"
|
|
39
|
-
| "Tanssikoulu Matleena"
|
|
40
|
-
| "Merja Tanjunen"
|
|
41
|
-
|
|
42
|
-
// OSLO
|
|
43
|
-
| "Fever Dance Oslo"
|
|
44
|
-
| "Pure Dance Official"
|
|
45
|
-
| "Dancecity"
|
|
46
|
-
| "Bachata Monthly"
|
|
47
|
-
| "Salsakompaniet"
|
|
48
|
-
|
|
49
|
-
// Tallinn
|
|
50
|
-
| "Bachata Studio Tallinn"
|
|
51
|
-
| "Casa De Baile"
|
|
52
|
-
| "Havana Moderna"
|
|
53
|
-
| "Crazy Lion Events"
|
|
54
|
-
|
|
55
|
-
// OTHER
|
|
56
|
-
| "Other";
|
|
57
|
-
|
|
58
|
-
export type OrganizerData = {
|
|
59
|
-
id: string;
|
|
60
|
-
name: OrganizerName;
|
|
61
|
-
email?: string;
|
|
62
|
-
website?: string;
|
|
63
|
-
city: City;
|
|
64
|
-
description?: {
|
|
65
|
-
fi: string;
|
|
66
|
-
en: string;
|
|
67
|
-
};
|
|
68
|
-
lastUpdated: string;
|
|
69
|
-
createdAt: string;
|
|
70
|
-
isFlagged: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* From 0 to 5. 0 is the highest priority.
|
|
73
|
-
*/
|
|
74
|
-
priority: number;
|
|
75
|
-
|
|
76
|
-
// Stripe for connected accounts
|
|
77
|
-
stripeAccountId?: string | null;
|
|
78
|
-
};
|
package/src/types/other.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export type Language = { code: LanguageCode };
|
|
2
|
-
|
|
3
|
-
export type LanguageCode = "en-gb" | "fi";
|
|
4
|
-
|
|
5
|
-
export type DayPoll = {
|
|
6
|
-
[eventId: string]: string[];
|
|
7
|
-
other: string[];
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type WeekendPoll = {
|
|
11
|
-
pollId: string;
|
|
12
|
-
createdAt: string;
|
|
13
|
-
friday: DayPoll;
|
|
14
|
-
saturday: DayPoll;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type FeatureFlags = {
|
|
18
|
-
multicity: boolean;
|
|
19
|
-
copenhagen: boolean;
|
|
20
|
-
oslo: boolean;
|
|
21
|
-
stockholm: boolean;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type RemoteConfigMessageType = {
|
|
25
|
-
severity: "info" | "warning";
|
|
26
|
-
message: string;
|
|
27
|
-
};
|
package/src/types/ticket.ts
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { Timestamp } from "firebase/firestore";
|
|
2
|
-
|
|
3
|
-
export type TicketStatus =
|
|
4
|
-
| "Confirmed"
|
|
5
|
-
| "Void"
|
|
6
|
-
| "Refunded"
|
|
7
|
-
| "Expired"
|
|
8
|
-
| "Used";
|
|
9
|
-
|
|
10
|
-
export type Ticket = {
|
|
11
|
-
/**
|
|
12
|
-
* ID of the ticket
|
|
13
|
-
*/
|
|
14
|
-
id: string;
|
|
15
|
-
/**
|
|
16
|
-
* ID of the event ticket
|
|
17
|
-
*/
|
|
18
|
-
ticketId: string;
|
|
19
|
-
eventId: string;
|
|
20
|
-
eventName: string;
|
|
21
|
-
eventDate: string;
|
|
22
|
-
/**
|
|
23
|
-
* Date of purchase in ISO format
|
|
24
|
-
*/
|
|
25
|
-
purchaseDate: string;
|
|
26
|
-
quantity: number;
|
|
27
|
-
paidAmount: MonetaryAmount;
|
|
28
|
-
originalAmount: MonetaryAmount;
|
|
29
|
-
ticketType: string;
|
|
30
|
-
/**
|
|
31
|
-
* ID of the user who originally purchased the ticket
|
|
32
|
-
*/
|
|
33
|
-
originalOwnerId: string;
|
|
34
|
-
/**
|
|
35
|
-
* ID of the user who owns the ticket
|
|
36
|
-
*/
|
|
37
|
-
owner: string;
|
|
38
|
-
status: TicketStatus;
|
|
39
|
-
isRefundable: boolean;
|
|
40
|
-
isTransferable: boolean;
|
|
41
|
-
paymentId: string;
|
|
42
|
-
appliedCoupon?: {
|
|
43
|
-
code: string;
|
|
44
|
-
discountAmount: number;
|
|
45
|
-
discountType: "fixed" | "percentage";
|
|
46
|
-
};
|
|
47
|
-
checkedInAt?: string;
|
|
48
|
-
notes?: string;
|
|
49
|
-
transferredAt?: string;
|
|
50
|
-
refundedAt?: string;
|
|
51
|
-
createdAt: Timestamp;
|
|
52
|
-
updatedAt: Timestamp;
|
|
53
|
-
/**
|
|
54
|
-
* @deprecated Replaced by originalOwnerId
|
|
55
|
-
*/
|
|
56
|
-
previousOwner: string[];
|
|
57
|
-
/**
|
|
58
|
-
* @deprecated Replaced by price.amount
|
|
59
|
-
*/
|
|
60
|
-
originalPrice?: number;
|
|
61
|
-
/**
|
|
62
|
-
* @deprecated Replaced by price.amount
|
|
63
|
-
*/
|
|
64
|
-
ticketPrice?: number;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type TicketTransfer = {
|
|
68
|
-
type: "transfer";
|
|
69
|
-
fromUserId: string;
|
|
70
|
-
toUserId: string;
|
|
71
|
-
timestamp: Timestamp;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export type CouponCode = {
|
|
75
|
-
code: string;
|
|
76
|
-
discountType: "fixed" | "percentage";
|
|
77
|
-
discountAmount: number;
|
|
78
|
-
startDate: string | null;
|
|
79
|
-
expiryDate: string | null;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export type EventTicket = {
|
|
83
|
-
id: string;
|
|
84
|
-
price: number;
|
|
85
|
-
price_details: MonetaryAmount;
|
|
86
|
-
eventId: string;
|
|
87
|
-
quantity: number;
|
|
88
|
-
hideQuantity: boolean;
|
|
89
|
-
amountSold: number;
|
|
90
|
-
coupons: CouponCode[] | null;
|
|
91
|
-
name: string;
|
|
92
|
-
description?: string;
|
|
93
|
-
maxQuantityPerPurchase?: number;
|
|
94
|
-
minQuantityPerPurchase?: number;
|
|
95
|
-
startDate: string | null;
|
|
96
|
-
endDate: string | null;
|
|
97
|
-
isTransferable: boolean;
|
|
98
|
-
isRefundable: boolean;
|
|
99
|
-
status: "published" | "draft" | "sold-out" | "unavailable";
|
|
100
|
-
/**
|
|
101
|
-
* Promotional period for the ticket
|
|
102
|
-
*/
|
|
103
|
-
promotionalPeriod: PromotionalPeriod | null;
|
|
104
|
-
/**
|
|
105
|
-
* @deprecated Replaced by name
|
|
106
|
-
*/
|
|
107
|
-
ticketType: string;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export type PromotionalPeriod = {
|
|
111
|
-
/**
|
|
112
|
-
* Discount amount during the promotional period. Can't be more than the price. unit: MAJOR
|
|
113
|
-
*/
|
|
114
|
-
discountAmount: number;
|
|
115
|
-
/**
|
|
116
|
-
* Start date of the promotional period (ISO string)
|
|
117
|
-
*/
|
|
118
|
-
startDate: string;
|
|
119
|
-
/**
|
|
120
|
-
* End date of the promotional period (ISO string)
|
|
121
|
-
*/
|
|
122
|
-
endDate: string;
|
|
123
|
-
/**
|
|
124
|
-
* Optional description of the promotion (e.g., "Early Bird", "Flash Sale")
|
|
125
|
-
*/
|
|
126
|
-
description?: string;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export type Payment = {
|
|
130
|
-
amount: number;
|
|
131
|
-
amount_capturable: number;
|
|
132
|
-
amount_details: {
|
|
133
|
-
tip: any;
|
|
134
|
-
};
|
|
135
|
-
amount_received: number;
|
|
136
|
-
application: string | null;
|
|
137
|
-
application_fee_amount: number | null;
|
|
138
|
-
automatic_payment_methods: {
|
|
139
|
-
allow_redirects: "always" | "never";
|
|
140
|
-
enabled: boolean;
|
|
141
|
-
};
|
|
142
|
-
canceled_at: string | null;
|
|
143
|
-
cancellation_reason: string | null;
|
|
144
|
-
capture_method: "automatic" | "manual";
|
|
145
|
-
client_secret: string;
|
|
146
|
-
confirmation_method: string;
|
|
147
|
-
created: number;
|
|
148
|
-
currency: string;
|
|
149
|
-
customer: string;
|
|
150
|
-
description: string | null;
|
|
151
|
-
id: string;
|
|
152
|
-
invoice: string | null;
|
|
153
|
-
last_payment_error: string | null;
|
|
154
|
-
latest_charge: string;
|
|
155
|
-
livemode: boolean;
|
|
156
|
-
metadata: Record<string, any>;
|
|
157
|
-
next_action: string | null;
|
|
158
|
-
object: string;
|
|
159
|
-
on_behalf_of: string | null;
|
|
160
|
-
payment_method_types: ("card" | "mobilepay")[];
|
|
161
|
-
payment_method_configuration_details: {
|
|
162
|
-
id: string;
|
|
163
|
-
};
|
|
164
|
-
payment_method_options: {
|
|
165
|
-
card: {
|
|
166
|
-
network?: string;
|
|
167
|
-
request_three_d_secure: string;
|
|
168
|
-
};
|
|
169
|
-
mobilepay: any;
|
|
170
|
-
};
|
|
171
|
-
processing: string | null;
|
|
172
|
-
receipt_email: string;
|
|
173
|
-
review: string | null;
|
|
174
|
-
setup_future_usage: string | null;
|
|
175
|
-
shipping: string | null;
|
|
176
|
-
source: string | null;
|
|
177
|
-
statement_descriptor: string | null;
|
|
178
|
-
statement_descriptor_suffix: string | null;
|
|
179
|
-
status: "succeeded" | string;
|
|
180
|
-
transfer_data: string | null;
|
|
181
|
-
transfer_group: string | null;
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
export type MonetaryAmount = {
|
|
185
|
-
amount: number;
|
|
186
|
-
currency: string;
|
|
187
|
-
unit: "MAJOR" | "MINOR";
|
|
188
|
-
};
|
package/src/types/user.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { City } from "./city.js";
|
|
2
|
-
import { DanceTag } from "./event.js";
|
|
3
|
-
import { OrganizerName } from "./organizer.js";
|
|
4
|
-
import { Ticket } from "./ticket.js";
|
|
5
|
-
|
|
6
|
-
export type Role = "admin" | "manager" | "organiser" | "user";
|
|
7
|
-
|
|
8
|
-
export type User = {
|
|
9
|
-
id: string;
|
|
10
|
-
email: string;
|
|
11
|
-
displayName: string;
|
|
12
|
-
createdAt: string;
|
|
13
|
-
lastUpdated?: string;
|
|
14
|
-
lastConnected?: string;
|
|
15
|
-
savedEvents: string[];
|
|
16
|
-
goingEvents: string[];
|
|
17
|
-
role: Role;
|
|
18
|
-
city: City | null;
|
|
19
|
-
followingOrganisers: OrganizerName[];
|
|
20
|
-
favoriteDance?: DanceTag;
|
|
21
|
-
fcmTokens?: string[];
|
|
22
|
-
notificationPreferences?: NotificationPreferences;
|
|
23
|
-
appVersion?: string;
|
|
24
|
-
deviceModel?: string;
|
|
25
|
-
platform?: string;
|
|
26
|
-
tickets?: Ticket[];
|
|
27
|
-
emailVerified: boolean;
|
|
28
|
-
stripeId?: string;
|
|
29
|
-
profilePicture?: {
|
|
30
|
-
id: string;
|
|
31
|
-
url: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Organiser and manager
|
|
35
|
-
managerCity?: City;
|
|
36
|
-
organiserId?: string | null;
|
|
37
|
-
// Deprecated
|
|
38
|
-
organiser?: OrganizerName;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type NotificationPreferences = {
|
|
42
|
-
all: boolean;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* This is used to show who is going to the event
|
|
47
|
-
*/
|
|
48
|
-
export type UserBadge = {
|
|
49
|
-
id: string;
|
|
50
|
-
displayName: string;
|
|
51
|
-
avatar?: string;
|
|
52
|
-
};
|
package/src/utils/date.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import dayjs from "dayjs";
|
|
2
|
-
import relativeTime from "dayjs/plugin/relativeTime.js";
|
|
3
|
-
import { Timestamp } from "firebase/firestore";
|
|
4
|
-
|
|
5
|
-
// Register the relativeTime plugin
|
|
6
|
-
dayjs.extend(relativeTime);
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Converts a Firestore Timestamp to a JavaScript Date object
|
|
10
|
-
* @param timestamp Firestore Timestamp or null/undefined
|
|
11
|
-
* @returns JavaScript Date object or null if input is null/undefined
|
|
12
|
-
*/
|
|
13
|
-
export const timestampToDate = (timestamp: Timestamp): Date => {
|
|
14
|
-
if (!timestamp) {
|
|
15
|
-
throw new Error("Timestamp is null or undefined");
|
|
16
|
-
}
|
|
17
|
-
return new Date(timestamp.seconds * 1000 + timestamp.nanoseconds / 1000000);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export function timestampToIsoString(timestamp: Timestamp) {
|
|
21
|
-
return new Date(timestamp.seconds * 1000).toISOString();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Converts a JavaScript Date to a Firestore Timestamp
|
|
26
|
-
* @param date JavaScript Date object or null/undefined
|
|
27
|
-
* @returns Firestore Timestamp or null if input is null/undefined
|
|
28
|
-
*/
|
|
29
|
-
export const dateToTimestamp = (date: Date): Timestamp => {
|
|
30
|
-
if (!date) {
|
|
31
|
-
throw new Error("Date is null or undefined");
|
|
32
|
-
}
|
|
33
|
-
return Timestamp.fromDate(date);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Formats a Firestore Timestamp to a string using the provided format
|
|
38
|
-
* Uses day.js library - install with: npm install dayjs
|
|
39
|
-
* @param timestamp Firestore Timestamp or null/undefined
|
|
40
|
-
* @param formatStr Format string compatible with day.js format function
|
|
41
|
-
* (see https://day.js.org/docs/en/display/format for format options)
|
|
42
|
-
* @param defaultValue Value to return if timestamp is null/undefined
|
|
43
|
-
* @returns Formatted date string or defaultValue if timestamp is null/undefined
|
|
44
|
-
*/
|
|
45
|
-
export const formatTimestamp = (
|
|
46
|
-
timestamp: Timestamp,
|
|
47
|
-
formatStr: string = "MMM D, YYYY"
|
|
48
|
-
): string => {
|
|
49
|
-
if (!timestamp) {
|
|
50
|
-
throw new Error("Timestamp is null or undefined");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Convert timestamp to Date
|
|
54
|
-
const date = new Date(
|
|
55
|
-
timestamp.seconds * 1000 + timestamp.nanoseconds / 1000000
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
// Use dayjs to format the date according to the format string
|
|
59
|
-
return dayjs(date).format(formatStr);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Checks if a Firestore Timestamp is before current time
|
|
64
|
-
* @param timestamp Firestore Timestamp to check
|
|
65
|
-
* @returns boolean indicating if timestamp is in the past
|
|
66
|
-
*/
|
|
67
|
-
export const isTimestampInPast = (timestamp: Timestamp): boolean => {
|
|
68
|
-
if (!timestamp) {
|
|
69
|
-
throw new Error("Timestamp is null or undefined");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Convert timestamp to milliseconds manually
|
|
73
|
-
const timestampMillis =
|
|
74
|
-
timestamp.seconds * 1000 + timestamp.nanoseconds / 1000000;
|
|
75
|
-
return timestampMillis < Date.now();
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Checks if a Firestore Timestamp is after current time
|
|
80
|
-
* @param timestamp Firestore Timestamp to check
|
|
81
|
-
* @returns boolean indicating if timestamp is in the future
|
|
82
|
-
*/
|
|
83
|
-
export const isTimestampInFuture = (timestamp: Timestamp): boolean => {
|
|
84
|
-
if (!timestamp) {
|
|
85
|
-
throw new Error("Timestamp is null or undefined");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Convert timestamp to milliseconds manually
|
|
89
|
-
const timestampMillis =
|
|
90
|
-
timestamp.seconds * 1000 + timestamp.nanoseconds / 1000000;
|
|
91
|
-
return timestampMillis > Date.now();
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Gets the relative time between now and a Firestore Timestamp (e.g. "2 hours ago", "in 3 days")
|
|
96
|
-
* Uses day.js with relativeTime plugin for localized relative time formatting
|
|
97
|
-
* @param timestamp Firestore Timestamp
|
|
98
|
-
* @returns String representation of relative time
|
|
99
|
-
*/
|
|
100
|
-
export const getRelativeTime = (timestamp: Timestamp): string => {
|
|
101
|
-
if (!timestamp) {
|
|
102
|
-
throw new Error("Timestamp is null or undefined");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Convert timestamp to milliseconds manually
|
|
106
|
-
const timestampMillis =
|
|
107
|
-
timestamp.seconds * 1000 + timestamp.nanoseconds / 1000000;
|
|
108
|
-
|
|
109
|
-
// Use dayjs to get relative time
|
|
110
|
-
return dayjs(timestampMillis).fromNow();
|
|
111
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"rootDir": "./src",
|
|
6
|
-
"sourceMap": true,
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"declarationDir": "./dist",
|
|
11
|
-
"emitDeclarationOnly": false,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"strict": true,
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
"moduleResolution": "nodenext"
|
|
16
|
-
},
|
|
17
|
-
"include": ["src/**/*"],
|
|
18
|
-
"exclude": ["node_modules", "dist"]
|
|
19
|
-
}
|