Skip to content

Commit

Permalink
Almost final designs for Segments and Filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajat Saxena committed Oct 23, 2023
1 parent 39a1280 commit a371eaf
Show file tree
Hide file tree
Showing 23 changed files with 692 additions and 326 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ coverage

# Text editors configurations
.vscode
.rgignore

# Env file
.env*.local
Expand Down
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions apps/web/components/admin/users/filter-chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default function FilterChip({
onRemove,
}: FilterChipProps) {
const { name, condition, value } = filter;

return (
<div className="text-sm flex flex-wrap py-[2px] px-[4px] items-center rounded bg-slate-200">
<div>
Expand Down
190 changes: 104 additions & 86 deletions apps/web/components/admin/users/filter-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { Form, FormField, Select, Button, FormSubmit } from "@courselit/components-library";
import { ScrollArea } from "@courselit/components-library";
import {
Form,
FormField,
Select,
Button,
FormSubmit,
} from "@courselit/components-library";
import React, { useState, FormEvent } from "react";
import {
POPUP_CANCEL_ACTION,
USER_FILTER_APPLY_BTN,
USER_FILTER_CANCEL_BTN,
USER_FILTER_CATEGORY_EMAIL,
USER_FILTER_CATEGORY_LAST_ACTIVE,
USER_FILTER_CATEGORY_PERMISSION,
Expand All @@ -19,99 +26,110 @@ import Filter from "../../../ui-models/filter";
import PopoverHeader from "./popover-header";

function EmailFilterEditor({ onApply }: { onApply: (...args: any[]) => any }) {
const [condition, setCondition] = useState(USER_FILTER_EMAIL_IS_EXACTLY);
const [value, setValue] = useState("");
const [condition, setCondition] = useState(USER_FILTER_EMAIL_IS_EXACTLY);
const [value, setValue] = useState("");

const onSubmit = (e: FormEvent) => {
e.preventDefault()
if (value) {
onApply({ condition, value })
} else {
onApply()
}
}
const onSubmit = (e: FormEvent) => {
e.preventDefault();
if (value) {
onApply({ condition, value });
} else {
onApply();
}
};

return (
<Form className="flex flex-col gap-2" onSubmit={onSubmit}>
<PopoverHeader>{USER_FILTER_CATEGORY_EMAIL}</PopoverHeader>
<Select
value={condition}
onChange={setCondition}
title=""
options={[
{
label: USER_FILTER_EMAIL_IS_EXACTLY,
value: USER_FILTER_EMAIL_IS_EXACTLY,
},
{
label: USER_FILTER_EMAIL_CONTAINS,
value: USER_FILTER_EMAIL_CONTAINS,
},
{
label: USER_FILTER_EMAIL_NOT_CONTAINS,
value: USER_FILTER_EMAIL_NOT_CONTAINS,
},
]}
/>
<FormField
name="value"
value={value}
label=""
onChange={(event: FormEvent) => setValue(event.target.value)}
/>
<div className="flex justify-between">
<Button
name="cancel"
variant="soft"
onClick={(e: FormEvent) => {
e.preventDefault()
onApply()
}}
>{USER_FILTER_CANCEL_BTN}</Button>
<FormSubmit focus text={USER_FILTER_APPLY_BTN} />
</div>
</Form>
);
return (
<Form
className="flex flex-col gap-2 p-2 max-w-[180px]"
onSubmit={onSubmit}
>
<PopoverHeader>{USER_FILTER_CATEGORY_EMAIL}</PopoverHeader>
<Select
value={condition}
onChange={setCondition}
title=""
options={[
{
label: USER_FILTER_EMAIL_IS_EXACTLY,
value: USER_FILTER_EMAIL_IS_EXACTLY,
},
{
label: USER_FILTER_EMAIL_CONTAINS,
value: USER_FILTER_EMAIL_CONTAINS,
},
{
label: USER_FILTER_EMAIL_NOT_CONTAINS,
value: USER_FILTER_EMAIL_NOT_CONTAINS,
},
]}
/>
<FormField
name="value"
value={value}
label=""
onChange={(event: FormEvent) => setValue(event.target.value)}
/>
<div className="flex justify-between">
<Button
name="cancel"
variant="soft"
onClick={(e: FormEvent) => {
e.preventDefault();
onApply();
}}
>
{POPUP_CANCEL_ACTION}
</Button>
<FormSubmit text={USER_FILTER_APPLY_BTN} />
</div>
</Form>
);
}

interface FilterEditorProps {
dismissPopover: (filter: Filter) => void;
dismissPopover: (filter: Filter) => void;
}
export default function FilterEditor({ dismissPopover }: FilterEditorProps) {
const [activeCategory, setActiveCategory] = useState("");
const categories = [
{ label: USER_FILTER_CATEGORY_EMAIL, id: "email" },
{ label: USER_FILTER_CATEGORY_PRODUCT, id: "product" },
{ label: USER_FILTER_CATEGORY_LAST_ACTIVE, id: "last_active" },
{ label: USER_FILTER_CATEGORY_SIGNED_UP, id: "signed_up" },
{ label: USER_FILTER_CATEGORY_SUBSCRIPTION, id: "subscription" },
{ label: USER_FILTER_CATEGORY_TAGGED, id: "tagged" },
{ label: USER_FILTER_CATEGORY_PERMISSION, id: "permission" },
];
const [activeCategory, setActiveCategory] = useState("");
const categories = [
{ label: USER_FILTER_CATEGORY_EMAIL, id: "email" },
{ label: USER_FILTER_CATEGORY_PRODUCT, id: "product" },
{ label: USER_FILTER_CATEGORY_LAST_ACTIVE, id: "last_active" },
{ label: USER_FILTER_CATEGORY_SIGNED_UP, id: "signed_up" },
{ label: USER_FILTER_CATEGORY_SUBSCRIPTION, id: "subscription" },
{ label: USER_FILTER_CATEGORY_TAGGED, id: "tagged" },
{ label: USER_FILTER_CATEGORY_PERMISSION, id: "permission" },
];

const changeFilter = (
value: Pick<Filter, "condition" | "value"> | undefined,
) => {
dismissPopover(value ? { name: activeCategory, ...value } : undefined);
};
const changeFilter = (
value: Pick<Filter, "condition" | "value"> | undefined,
) => {
dismissPopover(value ? { name: activeCategory, ...value } : undefined);
};

return (
<div className="px-1 py-1">
{!activeCategory && (
<div>
<PopoverHeader>{USER_FILTER_DROPDOWN_LABEL}</PopoverHeader>
<ul>
{categories.map((category) => (
<li
key={category.id}
className="cursor-pointer px-2 text-medium leading-none rounded-[3px] flex items-center h-8 relative select-none outline-none data-[disabled]:text-slate-200 data-[disabled]:pointer-events-none hover:bg-slate-200"
onClick={() => setActiveCategory(category.id)}
>
{category.label}
</li>
))}
</ul>
</div>
return (
<div className="">
{!activeCategory && (
<ScrollArea>
<div className="p-2">
<PopoverHeader>
{USER_FILTER_DROPDOWN_LABEL}
</PopoverHeader>
<ul className="mt-2">
{categories.map((category) => (
<li
key={category.id}
className="cursor-pointer text-medium leading-none rounded-[3px] flex items-center h-8 relative select-none outline-none data-[disabled]:text-slate-200 data-[disabled]:pointer-events-none hover:bg-slate-200"
onClick={() =>
setActiveCategory(category.id)
}
>
{category.label}
</li>
))}
</ul>
</div>
</ScrollArea>
)}
{activeCategory && activeCategory === "email" && (
<EmailFilterEditor onApply={changeFilter} />
Expand Down
66 changes: 38 additions & 28 deletions apps/web/components/admin/users/filter-save.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
import React, { useState, ChangeEvent } from "react";
import { Form, FormField, FormSubmit } from "@courselit/components-library";
import Filter from "../../../ui-models/filter";
import { BUTTON_SAVE, USER_FILTER_NEW_SEGMENT_NAME, USER_FILTER_SAVE_DESCRIPTION } from "../../../ui-config/strings";
import Segment from "../../../ui-models/segment";
import {
BUTTON_SAVE,
USER_FILTER_NEW_SEGMENT_NAME,
USER_FILTER_SAVE_DESCRIPTION,
} from "../../../ui-config/strings";
import { FormEvent } from "react";
import { FetchBuilder } from "@courselit/utils";
import { AppDispatch, AppState } from "@courselit/state-management";
import type { AppDispatch, AppState } from "@courselit/state-management";
import { connect } from "react-redux";
import { Address, AppMessage } from "@courselit/common-models";
import { ThunkDispatch } from "redux-thunk";
import type { ThunkDispatch } from "redux-thunk";
import { actionCreators } from "@courselit/state-management";
import { AnyAction } from "redux";
import type { AnyAction } from "redux";
import PopoverDescription from "./popover-description";

const { networkAction, setAppMessage } = actionCreators;

interface FilterSaveProps {
filters: Filter[];
address: Address;
dispatch: AppDispatch;
dismissPopover: (val: boolean, segments: {
name: string,
filters: Filter[]
}) => void;
dismissPopover: (segments?: Segment[]) => void;
}

function FilterSave({
filters,
address,
dispatch,
dismissPopover
dismissPopover,
}: FilterSaveProps) {
const [name, setName] = useState("");

const onSubmit = async (e: FormEvent) => {
e.preventDefault();
const mutation =`
const mutation = `
mutation {
segments: createSegment(
segmentData: {
Expand All @@ -46,7 +49,8 @@ function FilterSave({
name,
condition,
value
}
},
segmentId
}
}
`;
Expand All @@ -61,33 +65,39 @@ function FilterSave({
);
const response = await fetch.exec();
if (response.segments) {
console.log(response.segments)
dismissPopover(response.segments);
} else {
dismissPopover();
}
} catch (err) {
dispatch(setAppMessage(new AppMessage(err.message)));
} finally {
(dispatch as ThunkDispatch<AppState, null, AnyAction>)(
networkAction(false),
);
dismissPopover(true)
}
}
};

return (
<div className="max-w-[180px] p-1">
<p className="text-xs text-slate-500 mb-2">{USER_FILTER_SAVE_DESCRIPTION}</p>
<Form className="flex flex-col gap-2" onSubmit={onSubmit}>
<FormField
value={name}
label={USER_FILTER_NEW_SEGMENT_NAME}
onChange={(e: ChangeEvent<HTMLInputElement>) => setName(e.target.value)}
onSubmit={onSubmit} />
<div className="flex justify-end">
<FormSubmit text={BUTTON_SAVE} className="" />
</div>
</Form>
</div>
)
<div className="max-w-[180px] p-2">
<PopoverDescription>
{USER_FILTER_SAVE_DESCRIPTION}
</PopoverDescription>
<Form className="flex flex-col gap-2 mt-2" onSubmit={onSubmit}>
<FormField
value={name}
label={USER_FILTER_NEW_SEGMENT_NAME}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setName(e.target.value)
}
onSubmit={onSubmit}
/>
<div className="flex justify-end">
<FormSubmit text={BUTTON_SAVE} />
</div>
</Form>
</div>
);
}

const mapStateToProps = (state: AppState) => ({
Expand Down
Loading

0 comments on commit a371eaf

Please sign in to comment.