mirror of
https://github.com/raidendotai/cofounder
synced 2025-06-26 18:17:52 +00:00
redux boilerplate placeholder
This commit is contained in:
parent
b88615fe5e
commit
b127f30724
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
# Cofounder | Early alpha release
|
# Cofounder | Early alpha release
|
||||||
|
|
||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
https://github.com/user-attachments/assets/b78d25aa-7cd3-49ee-a6f8-a952a77c8096
|
https://github.com/user-attachments/assets/cfd09250-d21e-49fc-a29b-fa0c661abfc0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -149,9 +149,8 @@ archi/v1 is as follows :
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Some Credits
|
# Credits
|
||||||
|
|
||||||
- Cover art edited from image found in [patriciaklein.de](https://patriciaklein.de)
|
|
||||||
- Demo design systems built using Figma renders / UI kits from:
|
- Demo design systems built using Figma renders / UI kits from:
|
||||||
* blocks.pm by Hexa Plugin (see `cofounder/api/system/presets`)
|
* blocks.pm by Hexa Plugin (see `cofounder/api/system/presets`)
|
||||||
* google material
|
* google material
|
||||||
|
@ -28,6 +28,9 @@ DESIGNER_DESIGN_SYSTEM = "presets/shadcn" #"presets/shadcn"
|
|||||||
# enables : code review after code generated , augment features like searching for external apis to implement in server , ...
|
# enables : code review after code generated , augment features like searching for external apis to implement in server , ...
|
||||||
SWARM_ENABLE = TRUE
|
SWARM_ENABLE = TRUE
|
||||||
|
|
||||||
|
# OPTIONAL
|
||||||
|
COFOUNDER_NICKNAME = "Cofounder"
|
||||||
|
|
||||||
#STATE_CLOUD = TRUE # persist on cloud (firebase + cloudstorage)
|
#STATE_CLOUD = TRUE # persist on cloud (firebase + cloudstorage)
|
||||||
#FIREBASE_SERVICE_KEY_PATH = ""
|
#FIREBASE_SERVICE_KEY_PATH = ""
|
||||||
#GOOGLECLOUDSTORAGE_SERVICE_KEY_PATH = ""
|
#GOOGLECLOUDSTORAGE_SERVICE_KEY_PATH = ""
|
||||||
|
@ -210,7 +210,7 @@ async function uxDatamapViews({ context, data }) {
|
|||||||
|
|
||||||
let tasks = [];
|
let tasks = [];
|
||||||
|
|
||||||
const UVs = Object.keys(uxsitemap.structure.views.unique);
|
const UVs = Object.keys(uxsitemap?.structure?.views?.unique) || {};
|
||||||
if (UVs.length) {
|
if (UVs.length) {
|
||||||
_chunkify(UVs, 5).map((uniqueViewsIdsChunk) => {
|
_chunkify(UVs, 5).map((uniqueViewsIdsChunk) => {
|
||||||
let filteredUxSitemap = { views: { unique: {} } };
|
let filteredUxSitemap = { views: { unique: {} } };
|
||||||
@ -227,7 +227,8 @@ async function uxDatamapViews({ context, data }) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const GVs = Object.keys(uxsitemap.structure.views.shared);
|
|
||||||
|
const GVs = Object.keys(uxsitemap?.structure?.views?.shared) || {};
|
||||||
if (GVs.length) {
|
if (GVs.length) {
|
||||||
tasks.push({
|
tasks.push({
|
||||||
uxsitemap: { views: { shared: uxsitemap.structure.views.shared } }, // filtered ux sitemap with all shared views
|
uxsitemap: { views: { shared: uxsitemap.structure.views.shared } }, // filtered ux sitemap with all shared views
|
||||||
|
@ -10,8 +10,8 @@ async function promptRoot({ context, data }) {
|
|||||||
const { uxsitemap, uxdatamap, webapp } = data;
|
const { uxsitemap, uxdatamap, webapp } = data;
|
||||||
|
|
||||||
const viewsImportHead = [
|
const viewsImportHead = [
|
||||||
...Object.keys(uxsitemap.structure.views.shared),
|
...( Object.keys(uxsitemap?.structure?.views?.shared) || {} ),
|
||||||
...Object.keys(uxsitemap.structure.views.unique),
|
...( Object.keys(uxsitemap?.structure?.views?.unique) || {} ),
|
||||||
]
|
]
|
||||||
.map((viewId) => {
|
.map((viewId) => {
|
||||||
return `import ${viewId} from '@/components/views/${viewId}.tsx';`;
|
return `import ${viewId} from '@/components/views/${viewId}.tsx';`;
|
||||||
|
@ -16,7 +16,7 @@ async function webappViewGenerateMulti({ context, data }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const tasks = [
|
const tasks = [
|
||||||
...Object.keys(views.unique).map((viewId) => {
|
...( Object.keys(views?.unique) || {} ).map((viewId) => {
|
||||||
return {
|
return {
|
||||||
task: {
|
task: {
|
||||||
type: "view",
|
type: "view",
|
||||||
@ -28,7 +28,7 @@ async function webappViewGenerateMulti({ context, data }) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
...Object.keys(views.shared).map((viewId) => {
|
...( Object.keys(views?.shared) || {} ).map((viewId) => {
|
||||||
return {
|
return {
|
||||||
task: {
|
task: {
|
||||||
type: "view",
|
type: "view",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 61 KiB |
@ -1,197 +1,9 @@
|
|||||||
import {
|
import { configureStore } from "@reduxjs/toolkit";
|
||||||
configureStore,
|
|
||||||
createSlice,
|
|
||||||
createAsyncThunk,
|
|
||||||
PayloadAction,
|
|
||||||
} from "@reduxjs/toolkit";
|
|
||||||
import { useDispatch, useSelector } from "react-redux"; // Importing useDispatch and useSelector from react-redux
|
|
||||||
|
|
||||||
// Define types directly here as any
|
// Create a Redux store
|
||||||
type RecipePreview = any;
|
const store = configureStore({
|
||||||
type RecipeDetails = any;
|
reducer: {}, // Empty reducer to prevent crashing
|
||||||
|
|
||||||
interface AppState {
|
|
||||||
searchQuery: string;
|
|
||||||
latestRecipes: RecipePreview[] | null;
|
|
||||||
loadingLatestRecipes: boolean;
|
|
||||||
latestRecipesError: string | null;
|
|
||||||
allRecipes: RecipePreview[] | null;
|
|
||||||
loadingAllRecipes: boolean;
|
|
||||||
allRecipesError: string | null;
|
|
||||||
recipeDetails: RecipeDetails | null;
|
|
||||||
loadingRecipeDetails: boolean;
|
|
||||||
recipeDetailsError: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial state definition
|
|
||||||
const initialState: AppState = {
|
|
||||||
searchQuery: "",
|
|
||||||
latestRecipes: null,
|
|
||||||
loadingLatestRecipes: false,
|
|
||||||
latestRecipesError: null,
|
|
||||||
allRecipes: null,
|
|
||||||
loadingAllRecipes: false,
|
|
||||||
allRecipesError: null,
|
|
||||||
recipeDetails: null,
|
|
||||||
loadingRecipeDetails: false,
|
|
||||||
recipeDetailsError: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Asynchronous Actions (Thunks)
|
|
||||||
export const fetchLatestRecipes = createAsyncThunk(
|
|
||||||
"recipes/fetchLatestRecipes",
|
|
||||||
async (_, { rejectWithValue }) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch("http://localhost:1337/api/v1/recipes/latest");
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch latest recipes");
|
|
||||||
}
|
|
||||||
const data: RecipePreview[] = await response.json();
|
|
||||||
return data;
|
|
||||||
} catch (error) {
|
|
||||||
return rejectWithValue(
|
|
||||||
error instanceof Error ? error.message : "Unknown error",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const fetchAllRecipes = createAsyncThunk(
|
|
||||||
"recipes/fetchAllRecipes",
|
|
||||||
async (
|
|
||||||
{ offset = 0, limit = 20 }: { offset?: number; limit?: number },
|
|
||||||
{ rejectWithValue },
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`http://localhost:1337/api/v1/recipes?offset=${offset}&limit=${limit}`,
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch recipes");
|
|
||||||
}
|
|
||||||
const data: RecipePreview[] = await response.json();
|
|
||||||
return data;
|
|
||||||
} catch (error) {
|
|
||||||
return rejectWithValue(
|
|
||||||
error instanceof Error ? error.message : "Unknown error",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const fetchRecipeDetails = createAsyncThunk(
|
|
||||||
"recipes/fetchRecipeDetails",
|
|
||||||
async (id: number, { rejectWithValue }) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`http://localhost:1337/api/v1/recipes/${id}`);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch recipe details");
|
|
||||||
}
|
|
||||||
const data: RecipeDetails = await response.json();
|
|
||||||
return data;
|
|
||||||
} catch (error) {
|
|
||||||
return rejectWithValue(
|
|
||||||
error instanceof Error ? error.message : "Unknown error",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Slice
|
|
||||||
const recipeSlice = createSlice({
|
|
||||||
name: "recipes",
|
|
||||||
initialState,
|
|
||||||
reducers: {
|
|
||||||
setSearchQuery(state, action: PayloadAction<string>) {
|
|
||||||
state.searchQuery = action.payload;
|
|
||||||
},
|
|
||||||
resetAllRecipes(state) {
|
|
||||||
state.allRecipes = null;
|
|
||||||
state.allRecipesError = null;
|
|
||||||
state.loadingAllRecipes = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extraReducers: (builder) => {
|
|
||||||
// Latest Recipes
|
|
||||||
builder.addCase(fetchLatestRecipes.pending, (state) => {
|
|
||||||
state.loadingLatestRecipes = true;
|
|
||||||
state.latestRecipesError = null;
|
|
||||||
});
|
|
||||||
builder.addCase(
|
|
||||||
fetchLatestRecipes.fulfilled,
|
|
||||||
(state, action: PayloadAction<RecipePreview[]>) => {
|
|
||||||
state.latestRecipes = action.payload;
|
|
||||||
state.loadingLatestRecipes = false;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
builder.addCase(
|
|
||||||
fetchLatestRecipes.rejected,
|
|
||||||
(state, action: PayloadAction<any>) => {
|
|
||||||
state.loadingLatestRecipes = false;
|
|
||||||
state.latestRecipesError = action.payload;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// All Recipes
|
|
||||||
builder.addCase(fetchAllRecipes.pending, (state) => {
|
|
||||||
state.loadingAllRecipes = true;
|
|
||||||
state.allRecipesError = null;
|
|
||||||
});
|
|
||||||
builder.addCase(
|
|
||||||
fetchAllRecipes.fulfilled,
|
|
||||||
(state, action: PayloadAction<RecipePreview[]>) => {
|
|
||||||
state.allRecipes = state.allRecipes
|
|
||||||
? [...state.allRecipes, ...action.payload]
|
|
||||||
: action.payload;
|
|
||||||
state.loadingAllRecipes = false;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
builder.addCase(
|
|
||||||
fetchAllRecipes.rejected,
|
|
||||||
(state, action: PayloadAction<any>) => {
|
|
||||||
state.loadingAllRecipes = false;
|
|
||||||
state.allRecipesError = action.payload;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Recipe Details
|
|
||||||
builder.addCase(fetchRecipeDetails.pending, (state) => {
|
|
||||||
state.loadingRecipeDetails = true;
|
|
||||||
state.recipeDetailsError = null;
|
|
||||||
});
|
|
||||||
builder.addCase(
|
|
||||||
fetchRecipeDetails.fulfilled,
|
|
||||||
(state, action: PayloadAction<RecipeDetails>) => {
|
|
||||||
state.recipeDetails = action.payload;
|
|
||||||
state.loadingRecipeDetails = false;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
builder.addCase(
|
|
||||||
fetchRecipeDetails.rejected,
|
|
||||||
(state, action: PayloadAction<any>) => {
|
|
||||||
state.loadingRecipeDetails = false;
|
|
||||||
state.recipeDetailsError = action.payload;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Exports
|
// Export the store as default
|
||||||
export const { setSearchQuery, resetAllRecipes } = recipeSlice.actions;
|
|
||||||
|
|
||||||
export const store = configureStore({
|
|
||||||
reducer: {
|
|
||||||
recipes: recipeSlice.reducer,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
|
||||||
export type RootState = ReturnType<typeof store.getState>;
|
|
||||||
export type AppDispatch = typeof store.dispatch;
|
|
||||||
|
|
||||||
// Hook to access the redux store within a component
|
|
||||||
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
|
||||||
export const useAppSelector: (selector: (state: RootState) => any) => any =
|
|
||||||
useSelector;
|
|
||||||
|
|
||||||
export default store;
|
export default store;
|
Loading…
Reference in New Issue
Block a user