Page MenuHomePhabricator

D3266.id9828.diff
No OneTemporary

D3266.id9828.diff

diff --git a/web/apps/app-listing.react.js b/web/apps/app-listing.react.js
new file mode 100644
--- /dev/null
+++ b/web/apps/app-listing.react.js
@@ -0,0 +1,75 @@
+// @flow
+
+import { faCheckCircle } from '@fortawesome/free-regular-svg-icons';
+import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import * as React from 'react';
+import { useDispatch } from 'react-redux';
+
+import {
+ disableAppActionType,
+ enableAppActionType,
+} from 'lib/reducers/enabled-apps-reducer';
+import type { SupportedApps } from 'lib/types/enabled-apps';
+
+import SWMansionIcon from '../SWMansionIcon.react';
+import css from './apps.css';
+
+type Props = {
+ +id: SupportedApps | 'chat',
+ +alwaysEnabled: boolean,
+ +enabled: boolean,
+ +appName: string,
+ +appIcon: 'message-square' | 'calendar',
+ +appCopy: string,
+};
+
+function AppListing(props: Props): React.Node {
+ const { id, alwaysEnabled, enabled, appName, appIcon, appCopy } = props;
+ const dispatch = useDispatch();
+
+ const enableApp = React.useCallback(
+ () => dispatch({ type: enableAppActionType, payload: id }),
+ [dispatch, id],
+ );
+
+ const disableApp = React.useCallback(() => {
+ console.log('DISABLE');
+ dispatch({ type: disableAppActionType, payload: id });
+ }, [dispatch, id]);
+
+ const actionButton = React.useMemo(() => {
+ if (alwaysEnabled) {
+ return (
+ <div className={css.appListingIconState}>
+ <FontAwesomeIcon color="#808080" icon={faCheckCircle} />
+ </div>
+ );
+ }
+ return (
+ <div
+ className={css.appListingIconState}
+ onClick={enabled ? disableApp : enableApp}
+ >
+ <FontAwesomeIcon
+ color={enabled ? 'green' : 'white'}
+ icon={enabled ? faCheckCircle : faPlusCircle}
+ />
+ </div>
+ );
+ }, [alwaysEnabled, disableApp, enableApp, enabled]);
+ return (
+ <div className={css.appListingContainer}>
+ <div className={css.appListingIcon}>
+ <SWMansionIcon icon={appIcon} size={20} />
+ </div>
+ <div className={css.appListingTextContainer}>
+ <div className={css.appName}> {appName}</div>
+ <div className={css.appCopy}> {appCopy}</div>
+ </div>
+ {actionButton}
+ </div>
+ );
+}
+
+export default AppListing;
diff --git a/web/apps/apps-directory.react.js b/web/apps/apps-directory.react.js
--- a/web/apps/apps-directory.react.js
+++ b/web/apps/apps-directory.react.js
@@ -1,9 +1,51 @@
// @flow
import * as React from 'react';
+import { useSelector } from 'react-redux';
+
+import AppListing from './app-listing.react';
+import css from './apps.css';
+
+const APP_DIRECTORY_DATA = [
+ {
+ id: 'chat',
+ alwaysEnabled: true,
+ appName: 'Chat',
+ appIcon: 'message-square',
+ appCopy: 'Keep in touch with your community',
+ },
+ {
+ id: 'calendar',
+ alwaysEnabled: false,
+ appName: 'Calendar',
+ appIcon: 'calendar',
+ appCopy: 'Shared calendar for your community',
+ },
+];
function AppsDirectory(): React.Node {
- return <div style={{ color: 'white' }}>Apps directory</div>;
+ const enabledApps = useSelector(state => state.enabledApps);
+
+ const appData = React.useMemo(
+ () =>
+ APP_DIRECTORY_DATA.map(app => ({
+ ...app,
+ enabled: enabledApps[app.id] ?? true,
+ })),
+ [enabledApps],
+ );
+
+ const appItems = React.useMemo(
+ () => appData.map(item => <AppListing key={item.id} {...item} />),
+ [appData],
+ );
+
+ return (
+ <div className={css.appsDirectoryContainer}>
+ <div className={css.appsHeader}>Choose Apps</div>
+ <div className={css.appsDirectoryList}>{appItems}</div>
+ </div>
+ );
}
export default AppsDirectory;
diff --git a/web/apps/apps.css b/web/apps/apps.css
new file mode 100644
--- /dev/null
+++ b/web/apps/apps.css
@@ -0,0 +1,57 @@
+div.appsDirectoryContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+}
+
+div.appsHeader {
+ color: var(--fg);
+ font-size: var(--xl-font-20);
+ margin: 20px 0px 40px 40px;
+ font-weight: var(--semi-bold);
+}
+
+div.appsDirectoryList {
+ margin-left: 20px;
+ display: flex;
+ flex-direction: column;
+ row-gap: 10px;
+}
+
+div.appListingContainer {
+ color: white;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+
+div.appListingTextContainer {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+}
+
+div.appName {
+ font-size: var(--l-font-18);
+ font-weight: var(--semi-bold);
+ margin-bottom: 4px;
+}
+
+div.appCopy {
+ font-size: var(--xs-font-12);
+}
+
+div.appListingIcon {
+ padding: 0 20px;
+ align-self: stretch;
+ display: flex;
+ align-items: center;
+}
+
+div.appListingIconState {
+ padding: 0 20px;
+ align-self: stretch;
+ display: flex;
+ align-items: center;
+ font-size: var(--xl-font-20);
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 12:38 AM (22 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2532460
Default Alt Text
D3266.id9828.diff (4 KB)

Event Timeline