Skip to content

Commit

Permalink
Merge pull request #1070 from overthq/dashboard-features
Browse files Browse the repository at this point in the history
More dashboard features
  • Loading branch information
koredefashokun authored Jun 28, 2024
2 parents 7104c1f + 1bee8d0 commit 70ea499
Show file tree
Hide file tree
Showing 30 changed files with 583 additions and 163 deletions.
20 changes: 20 additions & 0 deletions api/src/collections/product-category/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ const createProductCategory: Resolver<CreateProductCategoryArgs> = async (
return category;
};

interface EditProductCategoryArgs {
categoryId: string;
input: {
name?: string;
description?: string;
};
}

const editProductCategory: Resolver<EditProductCategoryArgs> = async (
_,
{ categoryId, input },
ctx
) => {
return ctx.prisma.storeProductCategory.update({
where: { id: categoryId },
data: input
});
};

interface DeleteProductCategoryArgs {
categoryId: string;
}
Expand All @@ -74,6 +93,7 @@ export default {
Mutation: {
addProductToCategory,
createProductCategory,
editProductCategory,
deleteProductCategory,
removeProductFromCategory
}
Expand Down
15 changes: 15 additions & 0 deletions api/src/collections/product-category/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,22 @@ const category: Resolver = async (parent, _, ctx) => {
.category();
};

interface StoreProductCategoryArgs {
id: string;
}

const storeProductCategory: Resolver<StoreProductCategoryArgs> = async (
_,
{ id },
ctx
) => {
return ctx.prisma.storeProductCategory.findUnique({
where: { id }
});
};

export default {
Query: { storeProductCategory },
ProductCategory: { id, product, category },
StoreProductCategory: { store, products }
};
16 changes: 15 additions & 1 deletion api/src/collections/product-category/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ const ProductCategoryTypes = gql`
type StoreProductCategory {
id: ID!
name: String!
storeId: ID!
name: String!
description: String
store: Store!
products: [ProductCategory!]!
Expand All @@ -29,6 +30,11 @@ const ProductCategoryTypes = gql`
description: String
}
input EditCategoryInput {
name: String
description: String
}
input AddProductToCategoryInput {
productId: ID!
categoryId: ID!
Expand All @@ -39,8 +45,16 @@ const ProductCategoryTypes = gql`
categoryId: ID!
}
extend type Query {
storeProductCategory(id: ID!): StoreProductCategory
}
extend type Mutation {
createProductCategory(input: CreateCategoryInput!): StoreProductCategory!
editProductCategory(
categoryId: ID!
input: EditCategoryInput!
): StoreProductCategory!
deleteProductCategory(categoryId: ID!): StoreProductCategory!
addProductToCategory(input: AddProductToCategoryInput!): ProductCategory!
removeProductFromCategory(
Expand Down
7 changes: 5 additions & 2 deletions api/src/collections/store-manager/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const addStoreManager: Resolver<AddStoreManagerArgs> = async (
};

interface RemoveStoreManagerArgs {
storeId: string;
managerId: string;
}

Expand All @@ -30,10 +29,14 @@ const removeStoreManager: Resolver<RemoveStoreManagerArgs> = async (
args,
ctx
) => {
if (!ctx.storeId) {
throw new Error('No storeId specified');
}

return ctx.prisma.storeManager.delete({
where: {
storeId_managerId: {
storeId: args.storeId,
storeId: ctx.storeId,
managerId: args.managerId
}
}
Expand Down
2 changes: 1 addition & 1 deletion api/src/collections/store-manager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const StoreManagerTypes = gql`
extend type Mutation {
addStoreManager(input: AddStoreManagerInput): StoreManager!
removeStoreManager(storeId: ID!, managerId: ID!): StoreManager!
removeStoreManager(managerId: ID!): StoreManager!
}
`;

Expand Down
11 changes: 11 additions & 0 deletions api/src/services/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
interface StoreCacheData {
managers: string[];
}

export default class CacheService {
storeCache: Record<string, StoreCacheData>;

public isStoreManager(storeId: string, userId: string) {
return this.storeCache[storeId]?.managers.includes(userId) ?? false;
}
}
3 changes: 3 additions & 0 deletions api/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import CacheService from './cache';
import EmailService from './email';
import NotificationsService from './notifications';

export default class Services {
public notifications: NotificationsService;
public email: EmailService;
public cache: CacheService;

constructor() {
this.notifications = new NotificationsService();
this.email = new EmailService();
this.cache = new CacheService();
}
}
7 changes: 3 additions & 4 deletions apps/app/src/screens/Verify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ const VerifyAuthentication: React.FC = () => {
const { params } = useRoute<RouteProp<AppStackParamList, 'Verify'>>();
const logIn = useStore(state => state.logIn);
const [code, setCode] = React.useState('');
const { phone } = params;
const { email } = params;
const [{ fetching }, verify] = useVerifyMutation();

const handleSubmit = async () => {
// TODO: Could do with some more validation.
if (phone && code) {
const { data, error } = await verify({ input: { phone, code } });
if (email && code) {
const { data, error } = await verify({ input: { email, code } });

if (data?.verify) {
const { accessToken, userId } = data.verify;
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type AppStackParamList = {
Home: undefined;
Register: undefined;
Authenticate: undefined;
Verify: { phone: string };
Verify: { email: string };
Product: { productId: string };
Cart: { cartId: string };
'Add Card': undefined;
Expand Down
16 changes: 16 additions & 0 deletions apps/dashboard/graphql/Categories.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,28 @@ query Categories {
}
}

query Category($id: ID!) {
storeProductCategory(id: $id) {
id
name
description
}
}

mutation CreateProductCategory($input: CreateCategoryInput!) {
createProductCategory(input: $input) {
id
}
}

mutation EditProductCategory($categoryId: ID!, $input: EditCategoryInput!) {
editProductCategory(categoryId: $categoryId, input: $input) {
id
name
description
}
}

mutation DeleteProductCategory($categoryId: ID!) {
deleteProductCategory(categoryId: $categoryId) {
id
Expand Down
19 changes: 13 additions & 6 deletions apps/dashboard/graphql/Manager.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,16 @@ query Managers {
}
}

# mutation RemoveManager($userId: uuid!, $storeId: uuid!) {
# delete_store_managers_by_pk(store_id: $storeId, manager_id: $userId) {
# manager_id
# store_id
# }
# }
mutation AddStoreManager($input: AddStoreManagerInput!) {
addStoreManager(input: $input) {
id
storeId
}
}

mutation RemoveStoreManager($managerId: ID!) {
removeStoreManager(managerId: $managerId) {
id
storeId
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SelectGroup } from '@habiti/components';
import React from 'react';
import { View } from 'react-native';

import { useCategoriesQuery } from '../../types/api';

// TODO: This should ultimately be stored in form state.

const ProductCategories = () => {
const [{ data, fetching }] = useCategoriesQuery();
const [selectedCategory, setSelectedCategory] = React.useState<string>();

if (fetching || !data) {
return <View />;
}

return (
<SelectGroup
selected={selectedCategory}
onSelect={setSelectedCategory}
options={data.currentStore.categories.map(c => ({
title: c.name,
value: c.id
}))}
/>
);
};

export default ProductCategories;
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/product/ProductActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ProductActions = () => {
Alert.alert(
'Confirm delete',
'Are you sure you want to delete this product?',
[{ text: 'Cancel' }, { text: 'Delete' }]
[{ text: 'Cancel' }, { text: 'Delete', style: 'destructive' }]
);
};

Expand Down
11 changes: 3 additions & 8 deletions apps/dashboard/src/components/product/ProductMain.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Icon, TextButton } from '@habiti/components';
import { TextButton } from '@habiti/components';
import { useNavigation } from '@react-navigation/native';
import React from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { Pressable, View } from 'react-native';
import { View } from 'react-native';

import ProductForm from './ProductForm';
import type { ProductFormData } from '../../screens/AddProduct';
Expand Down Expand Up @@ -40,8 +40,7 @@ const ProductMain: React.FC<ProductMainProps> = ({ product, mode }) => {
});

if (error) {
console.log('Error while editing product: ');
console.log(error);
console.log(`Error while editing product:\n${error}`);
} else {
setToUpload([]);
}
Expand All @@ -57,13 +56,9 @@ const ProductMain: React.FC<ProductMainProps> = ({ product, mode }) => {
<TextButton
onPress={formMethods.handleSubmit(onSubmit)}
disabled={disabled || fetching}
style={{ marginRight: 12 }}
>
Save
</TextButton>
<Pressable>
<Icon name='more-horizontal' />
</Pressable>
</View>
);
}
Expand Down
41 changes: 20 additions & 21 deletions apps/dashboard/src/components/product/ProductOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,26 @@ const NoProductOptions = () => {
const { theme } = useTheme();

return (
<View style={{ paddingVertical: 8 }}>
<View
style={{
backgroundColor: theme.input.background,
padding: 12,
borderRadius: 6
}}
>
<Typography weight='medium' size='large'>
No product options
</Typography>
<Spacer y={4} />
<Typography variant='secondary' size='small'>
There are currently no options for this product. When you create
options, they will appear here.
</Typography>
<Spacer y={8} />
<View style={{ backgroundColor: theme.border.color, height: 1 }} />
<Spacer y={8} />
<TextButton>Add product option</TextButton>
</View>
<View
style={{
backgroundColor: theme.input.background,
padding: 12,
borderRadius: 6,
marginVertical: 8
}}
>
<Typography weight='medium' size='large'>
No product options
</Typography>
<Spacer y={4} />
<Typography variant='secondary'>
There are currently no options for this product. When you create
options, they will appear here.
</Typography>
<Spacer y={8} />
<View style={{ backgroundColor: theme.border.color, height: 1 }} />
<Spacer y={8} />
<TextButton>Add product option</TextButton>
</View>
);
};
Expand Down
33 changes: 16 additions & 17 deletions apps/dashboard/src/components/product/ProductReviews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,22 @@ const NoProductReviews = () => {
const { theme } = useTheme();

return (
<View style={{ paddingVertical: 8 }}>
<View
style={{
backgroundColor: theme.input.background,
padding: 12,
borderRadius: 6
}}
>
<Typography weight='medium' size='large'>
No reviews yet
</Typography>
<Spacer y={4} />
<Typography variant='secondary' size='small'>
This product has not received any reviews yet. When users post reviews
for this product, they will appear here.
</Typography>
</View>
<View
style={{
backgroundColor: theme.input.background,
padding: 12,
borderRadius: 6,
marginVertical: 8
}}
>
<Typography weight='medium' size='large'>
No reviews yet
</Typography>
<Spacer y={4} />
<Typography variant='secondary'>
This product has not received any reviews yet. When users post reviews
for this product, they will appear here.
</Typography>
</View>
);
};
Expand Down
Loading

0 comments on commit 70ea499

Please sign in to comment.