codingpixel-expo-app 0.1.0 → 0.1.1
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/fonts.js +3 -2
- package/dist/install.js +5 -0
- package/dist/patch.js +8 -9
- package/package.json +1 -1
- package/templates/base/src/core/redux/reducers.ts +1 -1
- package/templates/base/src/core/redux/slices/userSlice.ts +12 -4
- package/templates/base/src/core/tanstack/tanstack-keys.ts +3 -42
- package/templates/base/src/core/utils/endpoints.ts +5 -29
- package/templates/base/src/core/utils/types.ts +3 -41
- package/templates/base/src/ui/theme/fonts.ts +14 -3
- package/templates/base/src/core/hooks/.gitkeep +0 -0
- package/templates/base/src/core/services/.gitkeep +0 -0
- package/templates/base/src/features/.gitkeep +0 -0
- package/templates/base/src/ui/components/.gitkeep +0 -0
- package/templates/base/src/ui/theme/allFileStyles.ts +0 -39
package/dist/fonts.js
CHANGED
|
@@ -81,7 +81,9 @@ export function generateBottomSheetProviderBlocks(bottomSheet) {
|
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
83
|
* Convenience: build the full sentinel-replacement map for `patchLayout`.
|
|
84
|
-
*
|
|
84
|
+
* Note: `fonts.ts` ships as a static enum file (Deviation #10) — no
|
|
85
|
+
* `FONTS_OBJECT` sentinel is patched. The 6 `_layout.tsx` sentinels still get
|
|
86
|
+
* filled (or empty-dropped per `gatherAnswers`).
|
|
85
87
|
*/
|
|
86
88
|
export function buildLayoutReplacements(answers) {
|
|
87
89
|
const fonts = generateUseFontsBlocks(answers.primaryFont, answers.secondaryFont);
|
|
@@ -93,6 +95,5 @@ export function buildLayoutReplacements(answers) {
|
|
|
93
95
|
BOTTOM_SHEET_PROVIDER_IMPORT: bs.importBlock,
|
|
94
96
|
BOTTOM_SHEET_PROVIDER_OPEN: bs.openBlock,
|
|
95
97
|
BOTTOM_SHEET_PROVIDER_CLOSE: bs.closeBlock,
|
|
96
|
-
FONTS_OBJECT: generateFontsObject(answers.primaryFont, answers.secondaryFont),
|
|
97
98
|
};
|
|
98
99
|
}
|
package/dist/install.js
CHANGED
|
@@ -38,6 +38,11 @@ export function buildAlwaysInstalledList(workletsPkg) {
|
|
|
38
38
|
// Deviation #7 — Phase 7 patchBabel injects ["module-resolver", { alias }];
|
|
39
39
|
// Metro fails on first bundle if the plugin pkg isn't installed.
|
|
40
40
|
"babel-plugin-module-resolver",
|
|
41
|
+
// Deviation #11 — expo-router peer deps that `expo install expo-router`
|
|
42
|
+
// does NOT auto-install (Metro fails at bundle time with "Unable to
|
|
43
|
+
// resolve 'expo-linking' from .../expo-router/build/views/Unmatched.js").
|
|
44
|
+
"expo-linking",
|
|
45
|
+
"expo-constants",
|
|
41
46
|
];
|
|
42
47
|
}
|
|
43
48
|
export function buildConditionalDeps(answers) {
|
package/dist/patch.js
CHANGED
|
@@ -112,18 +112,17 @@ export function patchConstants(target, templatesRoot, answers) {
|
|
|
112
112
|
const out = applySentinels(source, { MEDIA_CONSTANTS: replacement }, p);
|
|
113
113
|
fs.writeFileSync(p, out);
|
|
114
114
|
}
|
|
115
|
-
// ---------- layout
|
|
115
|
+
// ---------- layout splice (Phase 6 step 4) ----------
|
|
116
|
+
// Deviation #10: `fonts.ts` ships as a static enum file (no FONTS_OBJECT
|
|
117
|
+
// sentinel), so this only touches `_layout.tsx`.
|
|
116
118
|
export function patchLayout(target, replacements) {
|
|
117
119
|
const layoutPath = path.join(target, "src/app/_layout.tsx");
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (!fileExists(p)) {
|
|
121
|
-
throw new Error(`patchLayout: ${p} missing — was applyBase run first?`);
|
|
122
|
-
}
|
|
123
|
-
const before = fs.readFileSync(p, "utf8");
|
|
124
|
-
const after = applySentinels(before, replacements, p);
|
|
125
|
-
fs.writeFileSync(p, after);
|
|
120
|
+
if (!fileExists(layoutPath)) {
|
|
121
|
+
throw new Error(`patchLayout: ${layoutPath} missing — was applyBase run first?`);
|
|
126
122
|
}
|
|
123
|
+
const before = fs.readFileSync(layoutPath, "utf8");
|
|
124
|
+
const after = applySentinels(before, replacements, layoutPath);
|
|
125
|
+
fs.writeFileSync(layoutPath, after);
|
|
127
126
|
}
|
|
128
127
|
// ---------- package.json scripts (Phase 7 step 1) ----------
|
|
129
128
|
export function patchPackageJsonScripts(target) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { combineReducers } from "@reduxjs/toolkit";
|
|
|
2
2
|
import { persistReducer } from "redux-persist";
|
|
3
3
|
|
|
4
4
|
import { reduxStorage } from "./mmkvStorage";
|
|
5
|
-
import
|
|
5
|
+
import userReducer from "./slices/userSlice";
|
|
6
6
|
|
|
7
7
|
export const rootReducer = combineReducers({
|
|
8
8
|
user: userReducer,
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Minimal user shape per SPEC §6 ("dummy user shape").
|
|
2
|
+
// `accessToken` is required by the axios interceptor in `core/utils/config.ts`
|
|
3
|
+
// — every request reads `store.getState().user?.accessToken` and attaches as
|
|
4
|
+
// `Bearer <token>` if present. Apps replace shape but must keep the field.
|
|
3
5
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
4
6
|
|
|
5
7
|
export type User = {
|
|
6
8
|
id: string | null;
|
|
7
9
|
name: string | null;
|
|
10
|
+
accessToken: string | null;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
const initialState: User = { id: null, name: null };
|
|
13
|
+
const initialState: User = { id: null, name: null, accessToken: null };
|
|
11
14
|
|
|
12
15
|
const userSlice = createSlice({
|
|
13
16
|
name: "user",
|
|
@@ -16,16 +19,21 @@ const userSlice = createSlice({
|
|
|
16
19
|
setUser: (state, action: PayloadAction<User>) => {
|
|
17
20
|
state.id = action.payload.id;
|
|
18
21
|
state.name = action.payload.name;
|
|
22
|
+
state.accessToken = action.payload.accessToken;
|
|
19
23
|
},
|
|
20
24
|
updateUser: (state, action: PayloadAction<Partial<User>>) => {
|
|
21
25
|
Object.assign(state, action.payload);
|
|
22
26
|
},
|
|
27
|
+
setAccessToken: (state, action: PayloadAction<string | null>) => {
|
|
28
|
+
state.accessToken = action.payload;
|
|
29
|
+
},
|
|
23
30
|
clearUser: (state) => {
|
|
24
31
|
state.id = null;
|
|
25
32
|
state.name = null;
|
|
33
|
+
state.accessToken = null;
|
|
26
34
|
},
|
|
27
35
|
},
|
|
28
36
|
});
|
|
29
37
|
|
|
30
|
-
export const { setUser, updateUser, clearUser } = userSlice.actions;
|
|
38
|
+
export const { setUser, updateUser, setAccessToken, clearUser } = userSlice.actions;
|
|
31
39
|
export default userSlice.reducer;
|
|
@@ -1,42 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// Dashboard
|
|
5
|
-
dashboard: ["coach", "dashboard"],
|
|
6
|
-
// Teams
|
|
7
|
-
teams: ["coach", "teams"],
|
|
8
|
-
teamDetails: (teamId: string) => ["coach", "teamDetails", teamId],
|
|
9
|
-
// Schedule
|
|
10
|
-
schedule: ["coach", "schedule"],
|
|
11
|
-
// Messages
|
|
12
|
-
messages: ["coach", "messages"],
|
|
13
|
-
messageDetails: (messageId: string) => ["coach", "messageDetails", messageId],
|
|
14
|
-
directChatInfo: (chatId: string) => ["directChatInfo", chatId],
|
|
15
|
-
directChatMessages: (chatId: string) => ["directChatMessages", chatId],
|
|
16
|
-
teamChatInfo: (teamId: string) => ["teamChatInfo", teamId],
|
|
17
|
-
teamChatMessages: (teamId: string) => ["teamChatMessages", teamId],
|
|
18
|
-
teamAnnouncements: (teamId: string) => ["teamAnnouncements", teamId],
|
|
19
|
-
// Payments
|
|
20
|
-
payments: ["coach", "payments"],
|
|
21
|
-
paymentsSummary: ["coach", "payments", "summary"],
|
|
22
|
-
paymentPlanDetail: (planId: string) => ["coach", "paymentPlanDetail", planId],
|
|
23
|
-
// Profile
|
|
24
|
-
|
|
25
|
-
// shared
|
|
26
|
-
playerDetails: (playerId: string) => ["shared", "playerDetails", playerId],
|
|
27
|
-
|
|
28
|
-
// parent
|
|
29
|
-
parentSchedule: ["parent", "schedule"],
|
|
30
|
-
parentDashboard: ["parent", "dashboard"],
|
|
31
|
-
myFamily: ["parent", "myFamily"],
|
|
32
|
-
programs: ["parent", "programs"],
|
|
33
|
-
programDetails: (id: string) => ["parent", "programDetails", id],
|
|
34
|
-
registration: ["parent", "registration"],
|
|
35
|
-
parentMessages: ["parent", "messages"],
|
|
36
|
-
parentMessageDetails: (messageId: string) => ["parent", "messageDetails", messageId],
|
|
37
|
-
parentPayments: ["parent", "payments"],
|
|
38
|
-
parentPaymentsSummary: ["parent", "payments", "summary"],
|
|
39
|
-
parentOrganizations: ["parent", "organizations"],
|
|
40
|
-
parentTeamInvitations: ["parent", "teamInvitations"],
|
|
41
|
-
parentTeamInvitationDetail: (id: string) => ["parent", "teamInvitationDetail", id],
|
|
42
|
-
};
|
|
1
|
+
// Empty registry — apps populate with their own query keys.
|
|
2
|
+
// Pattern: { listKey: ["list"], detailKey: (id: string) => ["detail", id] }
|
|
3
|
+
export const TANSTACK_KEYS = {};
|
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const ENDPOINTS = {
|
|
7
|
-
LOGIN: "auth/login",
|
|
8
|
-
// Dashboard
|
|
9
|
-
DASHBOARD: "coach/dashboard",
|
|
10
|
-
// Teams
|
|
11
|
-
TEAMS: "coach/teams",
|
|
12
|
-
TEAM_DETAILS: (teamId: string) => `coach/teams/${teamId}`,
|
|
13
|
-
// Schedule
|
|
14
|
-
SCHEDULE: "coach/schedule",
|
|
15
|
-
// Messages
|
|
16
|
-
MESSAGES: "coach/messages",
|
|
17
|
-
MESSAGE_DETAILS: (messageId: string) => `coach/messages/${messageId}`,
|
|
18
|
-
DIRECT_CHAT: (chatId: string) => `chat/direct/${chatId}`,
|
|
19
|
-
TEAM_CHAT: (teamId: string) => `chat/team/${teamId}`,
|
|
20
|
-
// Payments
|
|
21
|
-
PAYMENTS: "coach/payments",
|
|
22
|
-
PAYMENTS_SUMMARY: "coach/payments/summary",
|
|
23
|
-
PAYMENT_PLAN: (planId: string) => `coach/payment-plans/${planId}`,
|
|
24
|
-
// Profile
|
|
25
|
-
PROFILE: "coach/profile",
|
|
26
|
-
CHANGE_PASSWORD: "coach/change-password",
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export { BASE_URL, ENDPOINTS, SOCKET_URL };
|
|
1
|
+
// Empty endpoint registry — apps populate as backend API solidifies.
|
|
2
|
+
// `BASE_URL` is consumed by `core/utils/config.ts` (axios baseURL).
|
|
3
|
+
export const SOCKET_URL = "";
|
|
4
|
+
export const BASE_URL = "";
|
|
5
|
+
export const ENDPOINTS = {};
|
|
@@ -1,47 +1,9 @@
|
|
|
1
|
+
// Empty type registry — apps add domain types as features grow.
|
|
2
|
+
// `InsetsProps` is consumed by `ui/appComponents/appButton` and a few other
|
|
3
|
+
// shipped primitives, so it stays.
|
|
1
4
|
export interface InsetsProps {
|
|
2
5
|
top?: number;
|
|
3
6
|
bottom?: number;
|
|
4
7
|
left?: number;
|
|
5
8
|
right?: number;
|
|
6
9
|
}
|
|
7
|
-
|
|
8
|
-
export type TeamNextEvent = {
|
|
9
|
-
id: string;
|
|
10
|
-
monthLabel: string;
|
|
11
|
-
dayLabel: string;
|
|
12
|
-
title: string;
|
|
13
|
-
timeAndLocationLabel: string;
|
|
14
|
-
kind: ScheduleEventKind;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type TeamStatus = "active" | "inactive";
|
|
18
|
-
export type ScheduleEventKind = "game" | "practice";
|
|
19
|
-
|
|
20
|
-
export type Team = {
|
|
21
|
-
id: string;
|
|
22
|
-
name: string;
|
|
23
|
-
seasonLabel: string;
|
|
24
|
-
status: TeamStatus;
|
|
25
|
-
logoUri?: string;
|
|
26
|
-
playerCount: number;
|
|
27
|
-
coachCount: number;
|
|
28
|
-
eventCount: number;
|
|
29
|
-
nextEvent: TeamNextEvent | null;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type ScheduleRow = {
|
|
33
|
-
id: string;
|
|
34
|
-
monthLabel: string;
|
|
35
|
-
dayLabel: string;
|
|
36
|
-
title: string;
|
|
37
|
-
timeAndLocationLabel: string;
|
|
38
|
-
kind: ScheduleEventKind;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type PlayerTransaction = {
|
|
42
|
-
id: string;
|
|
43
|
-
invoiceNumber: string;
|
|
44
|
-
date: string;
|
|
45
|
-
amount: string;
|
|
46
|
-
status: "paid" | "unpaid";
|
|
47
|
-
};
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Empty font registry — drop matching .ttf files into `assets/fonts/` and
|
|
2
|
+
// fill the enum values with PostScript names (e.g. `BOLD = "Inter-Bold"`).
|
|
3
|
+
// Wire `useFonts(...)` in `src/app/_layout.tsx` to actually load them.
|
|
4
|
+
export const enum Fonts {
|
|
5
|
+
BOLD = "",
|
|
6
|
+
EXTRA_BOLD = "",
|
|
7
|
+
EXTRA_LIGHT = "",
|
|
8
|
+
MEDIUM = "",
|
|
9
|
+
REGULAR = "",
|
|
10
|
+
SEMI_BOLD = "",
|
|
11
|
+
ITALIC = "",
|
|
12
|
+
LIGHT = "",
|
|
13
|
+
THIN = "",
|
|
14
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from "react-native";
|
|
2
|
-
import { Colors } from "./colors";
|
|
3
|
-
import { RF } from "./responsive";
|
|
4
|
-
|
|
5
|
-
export const AllStyles = StyleSheet.create({
|
|
6
|
-
backdropAbsoluteBlur: {
|
|
7
|
-
...StyleSheet.absoluteFillObject,
|
|
8
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
9
|
-
shadowColor: "#000",
|
|
10
|
-
shadowOffset: { width: 0, height: -2 },
|
|
11
|
-
shadowOpacity: 0.25,
|
|
12
|
-
shadowRadius: 8,
|
|
13
|
-
elevation: 8,
|
|
14
|
-
zIndex: 1,
|
|
15
|
-
},
|
|
16
|
-
shadowBackdrop: {
|
|
17
|
-
...StyleSheet.absoluteFillObject,
|
|
18
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
19
|
-
shadowColor: "#000",
|
|
20
|
-
shadowOffset: { width: 0, height: -2 },
|
|
21
|
-
shadowOpacity: 0.25,
|
|
22
|
-
shadowRadius: 8,
|
|
23
|
-
elevation: 8,
|
|
24
|
-
zIndex: 1,
|
|
25
|
-
},
|
|
26
|
-
modalBorderStyle: {
|
|
27
|
-
borderTopLeftRadius: RF(20),
|
|
28
|
-
borderTopRightRadius: RF(20),
|
|
29
|
-
backgroundColor: Colors.GRAY_1,
|
|
30
|
-
},
|
|
31
|
-
messageListContainer: { gap: RF(16), padding: RF(16) },
|
|
32
|
-
modalBackgroundColor: {
|
|
33
|
-
backgroundColor: Colors.GRAY_1,
|
|
34
|
-
},
|
|
35
|
-
fullWidthButton: {
|
|
36
|
-
width: "100%",
|
|
37
|
-
},
|
|
38
|
-
shadowOffset: { width: 0, height: 2 },
|
|
39
|
-
});
|