Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add post directly to timeline #1802

Merged
merged 13 commits into from
Apr 13, 2023
Merged
2 changes: 1 addition & 1 deletion src/components/Expericence/Experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const Experience: React.FC<ExperienceProps> = props => {
const experienceId = userExperience.experience.id;
const userExperienceId = userExperience.id;
const link =
publicRuntimeConfig.appAuthURL + `/type=experience&id=${experienceId}`;
publicRuntimeConfig.appAuthURL + `/?type=experience&id=${experienceId}`;
const { userExperiencesMeta } = useExperienceHook();
const totalOwnedExperience =
userExperiencesMeta.additionalData?.totalOwnedExperience ?? 0;
Expand Down
89 changes: 89 additions & 0 deletions src/components/ExperienceList/ExperienceListBarCreatePost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState } from 'react';

import { Experience as ExperienceCard } from '../ExpericenceRightBar';
import { useStyles } from './ExperienceList.style';

import { WrappedExperience } from 'src/interfaces/experience';
import { TimelineType } from 'src/interfaces/timeline';
import { User } from 'src/interfaces/user';

type ExperienceListProps = {
experiences: WrappedExperience[];
isOnHomePage?: boolean;
user?: User;
anonymous?: boolean;
selectable: boolean;
viewPostList: (type: TimelineType, userExperience: WrappedExperience) => void;
onSubscribe?: (experienceId: string) => void;
onClone?: (experienceId: string) => void;
onPreview?: (experienceId: string) => void;
onDelete?: (experienceId: string) => void;
onUnsubscribe?: (experienceId: string) => void;
};

export const ExperienceListBarCreatePost: React.FC<ExperienceListProps> =
props => {
const {
experiences,
user,
anonymous = false,
selectable,
viewPostList,
onDelete,
onUnsubscribe,
onSubscribe,
onClone,
} = props;

const classes = useStyles();
const [selectedExperienceIds, setSelectedExperienceIds] = useState<
string[]
>([]);

//TODO: still unable to only select one experience card
const handleSelectExperience =
(userExperience: WrappedExperience) => () => {
if (userExperience) {
if (selectedExperienceIds.includes(userExperience.experience.id)) {
setSelectedExperienceIds(
selectedExperienceIds.filter(
id => id !== userExperience.experience.id,
),
);
} else {
setSelectedExperienceIds([
...selectedExperienceIds,
userExperience.experience.id,
]);
}
}

viewPostList(TimelineType.EXPERIENCE, userExperience);
};

return (
<div className={classes.root}>
{experiences.map(item => (
<div key={item.experience.id}>
<ExperienceCard
user={user}
anonymous={anonymous}
userExperience={item}
selected={
Boolean(selectedExperienceIds.length) &&
selectedExperienceIds.includes(item.experience.id)
}
selectable={selectable}
onSelect={handleSelectExperience(item)}
onDelete={onDelete}
onUnsubscribe={onUnsubscribe}
onSubscribe={onSubscribe}
onClone={onClone}
/>
</div>
))}
</div>
);
};

export default ExperienceListBarCreatePost;
83 changes: 83 additions & 0 deletions src/components/ExperiencePost/Experience.container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';

import { useRouter } from 'next/router';

import { useStyles } from './Experience.styles';
import { ExperiencePost } from './ExperiencePost';

import debounce from 'lodash/debounce';
import { TopNavbarComponent } from 'src/components/atoms/TopNavbar';
import { useExperienceHook } from 'src/hooks/use-experience-hook';
import { useSearchHook } from 'src/hooks/use-search.hooks';
import { useUpload } from 'src/hooks/use-upload.hook';
import { ExperienceProps } from 'src/interfaces/experience';
import i18n from 'src/locale';

export const ExperienceContainer: React.FC = () => {
// TODO: separate hook for tag, people and experience
const {
selectedExperience,
tags,
people,
saveExperience,
searchTags,
searchPeople,
loadExperience,
} = useExperienceHook();
const { searchUsers, users } = useSearchHook();
const style = useStyles();

const { uploadImage } = useUpload();
const router = useRouter();

const onImageUpload = async (files: File[]) => {
const url = await uploadImage(files[0]);

return url ?? '';
};

const onSave = (attributes: ExperienceProps) => {
saveExperience(attributes, (experienceId: string) => {
router.push(`/experience/${experienceId}`);

loadExperience();
});
};

const handleSearchTags = debounce((query: string) => {
searchTags(query);
}, 300);

const handleSearchPeople = debounce((query: string) => {
searchPeople(query);
}, 300);

const handleSearchUser = debounce((query: string) => {
searchUsers(query);
}, 300);

return (
<>
<div className={style.mb}>
<TopNavbarComponent
description={i18n.t('TopNavbar.Subtitle.Experience_Create')}
sectionTitle={i18n.t('TopNavbar.Title.Experience')}
/>
</div>
<div className={style.box}>
<ExperiencePost
isEdit={false}
experience={selectedExperience}
tags={tags}
people={people}
onSearchTags={handleSearchTags}
onImageUpload={onImageUpload}
onSearchPeople={handleSearchPeople}
onSave={onSave}
onSearchUser={handleSearchUser}
users={users}
/>
</div>
</>
);
};
178 changes: 178 additions & 0 deletions src/components/ExperiencePost/Experience.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import {
createStyles,
makeStyles,
Theme,
alpha,
} from '@material-ui/core/styles';

export const useStyles = makeStyles((theme: Theme) =>
createStyles({
'@global': {
' .MuiAutocomplete-option[aria-selected="true"]': {
background: 'none',
},
' .MuiAutocomplete-option[data-focus="true"]': {
backgroundColor: alpha('#FFC857', 0.15),
},
' .MuiAutocomplete-tag .MuiSvgIcon-root': {
width: 14,
height: 14,
},

' .MuiFormHelperText-root': {
marginLeft: 0,

[theme.breakpoints.down('xs')]: {
fontSize: 12,
},
},
},
root: {
background: '#FFF',
borderRadius: 10,
marginBottom: 24,

'& .MuiAutocomplete-popupIndicatorOpen': {
transform: 'none',
},

[theme.breakpoints.down('xs')]: {
padding: '20px',
},
},
header: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: theme.spacing(2),
},
content: {
display: 'flex',
flexDirection: 'row',
gap: theme.spacing(3),
},
row1: {
minWidth: 100,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
paddingTop: 8,
gap: 8,
},
boxImage: {
width: 100,
height: 100,
borderRadius: 10,
border: '2px dashed #C2C2C2',
backgroundColor: '#F5F5F5',
},
row2: {
width: '100%',
overflow: 'hidden',
paddingTop: 8,
},
title: {
marginBottom: 30,
fontSize: theme.typography.h5.fontSize,
fontWeight: 400,
},
preview: {
marginBottom: 30,

'& .MuiListItem-root:hover': {
backgroundColor: alpha('#FFC857', 0.15),

'&::before,&::after': {
content: '""',
position: 'absolute',
width: 30,
height: '100%',
top: 0,
backgroundColor: alpha('#FFC857', 0.15),
},
'&::before': {
left: -30,
},
'&::after': {
right: -30,
},
},
},
postTextContainer: {
border: '1px solid #E5E5E5',
width: '100%',
padding: '20px',
borderRadius: '5px',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',
marginBottom: 36,
},
textPost: {
fontWeight: 600,
fontSize: 18,
},
textPostDetail: {
fontWeight: 400,
fontSize: 14,
marginTop: 9,
},
label: {
background: '#FFF',
paddingLeft: 6,
paddingRight: 6,
},
social: {
color: theme.palette.primary.main,
},
people: {},
removePeople: {
'& .MuiSvgIcon-root': {
fill: 'currentColor',
},
},
mb: {
marginBottom: '10px',
},
loading: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
zIndex: 999,
width: '100%',
height: '100%',
textAlign: 'center',
},
option: {
width: '100%',
},
counter: {
position: 'absolute',
right: 0,
bottom: 0,
color: '#898888',
},
box: {
[theme.breakpoints.down('xs')]: {
padding: '0px 20px 20px 20px',
},
},
fill: {
fill: 'currentColor',
'& .MuiSvgIcon-root': {
fill: 'currentColor',
},
},
formControl: {
marginBottom: 0,
},
customVisibility: {
maxHeight: '300px',
overflowY: 'scroll',
border: '1px solid #FFD24D',
borderRadius: '4px',
padding: '0 10px',
},
}),
);
Loading