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 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
- * Includes both layout sentinels and the fonts.ts sentinel.
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 + fonts splice (Phase 6 step 4) ----------
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
- const fontsPath = path.join(target, "src/ui/theme/fonts.ts");
119
- for (const p of [layoutPath, fontsPath]) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codingpixel-expo-app",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Opinionated Expo app scaffolder mirroring MyRoster conventions.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 { userReducer } from "./slices/userSlice";
5
+ import userReducer from "./slices/userSlice";
6
6
 
7
7
  export const rootReducer = combineReducers({
8
8
  user: userReducer,
@@ -1,13 +1,16 @@
1
- // Deviation #5 (docs/MIRROR_NOTES.md): minimal user shape per SPEC §6 ("dummy
2
- // user shape"). Apps replace with their actual auth model.
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
- export const TANSTACK_KEYS = {
2
- // coach
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
- const SOCKET_URL = "";
2
-
3
- const BASE_URL = `${SOCKET_URL}api/`;
4
-
5
- // placeholder update when backend API is finalized
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
- // Generated at scaffold time by `patchLayout` (Phase 6) based on the user's
2
- // EXPO_PRIMARY_FONT / EXPO_SECONDARY_FONT answers.
3
- // @@FONTS_OBJECT@@
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
- });