redux boilerplate placeholder

This commit is contained in:
raidendotai 2024-09-24 10:29:29 +01:00
parent b88615fe5e
commit b127f30724
7 changed files with 19 additions and 204 deletions

View File

@ -1,5 +1,5 @@
![cofounder-og](https://github.com/user-attachments/assets/a9cda40f-0bf8-423b-815d-d8d6891f7ce3)
![cofounder-og-black](https://github.com/user-attachments/assets/b4e51f02-59e4-4540-ac14-e1f40e20a658)
# 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:
* blocks.pm by Hexa Plugin (see `cofounder/api/system/presets`)
* google material

View File

@ -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 , ...
SWARM_ENABLE = TRUE
# OPTIONAL
COFOUNDER_NICKNAME = "Cofounder"
#STATE_CLOUD = TRUE # persist on cloud (firebase + cloudstorage)
#FIREBASE_SERVICE_KEY_PATH = ""
#GOOGLECLOUDSTORAGE_SERVICE_KEY_PATH = ""

View File

@ -210,7 +210,7 @@ async function uxDatamapViews({ context, data }) {
let tasks = [];
const UVs = Object.keys(uxsitemap.structure.views.unique);
const UVs = Object.keys(uxsitemap?.structure?.views?.unique) || {};
if (UVs.length) {
_chunkify(UVs, 5).map((uniqueViewsIdsChunk) => {
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) {
tasks.push({
uxsitemap: { views: { shared: uxsitemap.structure.views.shared } }, // filtered ux sitemap with all shared views

View File

@ -10,8 +10,8 @@ async function promptRoot({ context, data }) {
const { uxsitemap, uxdatamap, webapp } = data;
const viewsImportHead = [
...Object.keys(uxsitemap.structure.views.shared),
...Object.keys(uxsitemap.structure.views.unique),
...( Object.keys(uxsitemap?.structure?.views?.shared) || {} ),
...( Object.keys(uxsitemap?.structure?.views?.unique) || {} ),
]
.map((viewId) => {
return `import ${viewId} from '@/components/views/${viewId}.tsx';`;

View File

@ -16,7 +16,7 @@ async function webappViewGenerateMulti({ context, data }) {
};
const tasks = [
...Object.keys(views.unique).map((viewId) => {
...( Object.keys(views?.unique) || {} ).map((viewId) => {
return {
task: {
type: "view",
@ -28,7 +28,7 @@ async function webappViewGenerateMulti({ context, data }) {
},
};
}),
...Object.keys(views.shared).map((viewId) => {
...( Object.keys(views?.shared) || {} ).map((viewId) => {
return {
task: {
type: "view",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,197 +1,9 @@
import {
configureStore,
createSlice,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { useDispatch, useSelector } from "react-redux"; // Importing useDispatch and useSelector from react-redux
import { configureStore } from "@reduxjs/toolkit";
// Define types directly here as any
type RecipePreview = any;
type RecipeDetails = any;
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;
},
);
},
// Create a Redux store
const store = configureStore({
reducer: {}, // Empty reducer to prevent crashing
});
// Exports
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 the store as default
export default store;