Skip to content

Commit

Permalink
Merge pull request #198 from daodaoedu/dev
Browse files Browse the repository at this point in the history
Merge to prod
  • Loading branch information
vincentxuu authored Dec 30, 2024
2 parents 1e04917 + 57caab8 commit 90980b5
Show file tree
Hide file tree
Showing 35 changed files with 279 additions and 545 deletions.
2 changes: 1 addition & 1 deletion components/Group/Form/Form.styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const StyledContainer = styled.main`
font-size: 14px;
}
@media (max-width: 760px) {
@media (max-width: 767px) {
padding: 20px;
}
`;
Expand Down
6 changes: 3 additions & 3 deletions components/Group/Form/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function GroupForm({
return (
<ProtectedComponent>
<StyledContainer>
<StyledPaper className="p-10 mb-4 md:w-[720px]">
<StyledPaper className="p-10 mb-4 w-full md:w-[720px]">
<StyledHeading>
{isCreateMode ? '發起揪團' : '編輯揪團'}
</StyledHeading>
Expand Down Expand Up @@ -145,7 +145,7 @@ export default function GroupForm({
placeholder="希望在什麼時間舉行?"
/>
</StyledPaper>
<StyledPaper className="p-10 mb-4 md:w-[720px]">
<StyledPaper className="p-10 mb-4 w-full md:w-[720px]">
<Fields.TextField
label="想找的夥伴"
name="partnerStyle"
Expand Down Expand Up @@ -215,7 +215,7 @@ export default function GroupForm({
helperText="標籤填寫完成後,會用 Hashtag 的形式呈現,例如: #一起學日文"
/>
</StyledPaper>
<StyledPaper className="md:w-[720px]">
<StyledPaper className="w-full md:w-[720px]">
<Fields.DateRadio
label="揪團期限"
name="deadline"
Expand Down
141 changes: 99 additions & 42 deletions components/Marathon/SignUp/MarathonForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export default function MarathonForm({
const reduxDispatch = useDispatch();
const [hasLoaded, setHasLoaded] = useState(false);
const [errors, setErrors] = useState({});
const [hasErrors, setHasErrors] = useState(false);
const marathonState = useSelector((state) => { return state.marathon; });
const localStorgeStored = window.localStorage.getItem('newMarathon');
const editingMarathon = localStorgeStored ? JSON.parse(localStorgeStored) : null;
Expand All @@ -87,20 +86,6 @@ export default function MarathonForm({
};
const [newMarathon, setNewMarathon] = useReducer(marathonFormReducer, initialState());

const onNextStep = () => {
if (hasErrors) {
toast.error('請修正錯誤');
} else {
reduxDispatch(updateNewMarathon(newMarathon));
setCurrentStep(currentStep + 1);
}
};

const onPrevStep = () => {
reduxDispatch(updateNewMarathon(newMarathon));
setCurrentStep(currentStep - 1);
};

const validators = {
required: (value) => {
return value.trim().length > 0;
Expand All @@ -110,50 +95,74 @@ export default function MarathonForm({
return names.length === milestonesLength;
}
};
const validateRules = {

const marathonDataMap = {
title: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'title',
validate: validators.required,
message: '請填寫表格',
},
description: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'description',
validate: validators.required,
message: '請填寫計畫敘述',
},
motivationDescription: {
dispatchType: 'UPDATE_MOTIVATION_FIELD',
dispatchKey: 'description',
validate: validators.required,
message: '請填寫學習動機',
},
outcomesDescription: {
dispatchType: 'UPDATE_OUTCOMES_FIELD',
dispatchKey: 'description',
validate: validators.required,
message: '請填寫學習成果',
},
goals: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'goals',
validate: validators.required,
message: '請填寫學習目標',
},
content: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'content',
validate: validators.required,
message: '請填寫學習內容',
},
milestonesName: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'milestones',
validate: (value) => {
return validators.allMilestonesNameRequired(value, newMarathon.milestones?.length);
},
message: '請填寫每週/隔週里程碑目標',
},
strategiesDescription: {
dispatchType: 'UPDATE_STRATEGIES_FIELD',
dispatchKey: 'description',
validate: validators.required,
message: '請填寫學習策略',
},
resources: {
dispatchType: 'UPDATE_FIELD',
dispatchKey: 'resources',
validate: validators.required,
message: '請填寫學習資源'
}
};

/**
* @param {string} name - The name of the field to validate.
* @param {*} input - The input value to validate.
* @returns {boolean} - Returns true if the input value passes validation, otherwise false.
*/
const handleValidate = (name, input) => {
const validateResult = validateRules[name]?.validate(input);
const errorMessage = validateRules[name]?.message;
const validateResult = marathonDataMap[name]?.validate(input);
const errorMessage = marathonDataMap[name]?.message;
if (validateResult) {
setErrors((prevErrors) =>
Object.fromEntries(Object.entries(prevErrors).filter(([key]) => key !== name))
Expand All @@ -168,22 +177,75 @@ export default function MarathonForm({
}
return validateResult;
};
const handleValidateAll = () => {
const newErrors = {};
let isValid = true;
Object.entries(marathonDataMap).forEach(([name, fieldData]) => {
const { validate, message } = fieldData;
let input;
if (validate) {
switch (name) {
case 'milestonesName':
input = newMarathon.milestones;
break;
case 'motivationDescription':
input = newMarathon.motivation?.description;
break;
case 'strategiesDescription':
input = newMarathon.strategies?.description;
break;
case 'outcomesDescription':
input = newMarathon.outcomes?.description;
break;
default:
input = newMarathon[name];
break;
}
const validationPassed = validate(input);

if (!validationPassed) {
newErrors[name] = { message: message || "驗證失敗" };
isValid = false;
}
}
});
setErrors(newErrors);
return isValid;
};
const handleOnChange = (
stateDispatchType,
stateDispatchKey,
name,
value,
validateName,
) => {
if (stateDispatchType && stateDispatchKey) {
const type = marathonDataMap[name]?.dispatchType;
const key = marathonDataMap[name]?.dispatchKey;

if (type && key) {
setNewMarathon({
type: stateDispatchType,
payload: { key: stateDispatchKey, value }
type,
payload: { key, value }
});
}
if (validateName) {
handleValidate(validateName, value);

if (name) {
handleValidate(name, value);
}
};

const onNextStep = () => {
const isValid = handleValidateAll();
if (!isValid) {
toast.error('請修正錯誤');
} else {
reduxDispatch(updateNewMarathon(newMarathon));
setCurrentStep(currentStep + 1);
}
};

const onPrevStep = () => {
reduxDispatch(updateNewMarathon(newMarathon));
setCurrentStep(currentStep - 1);
};

useEffect(() => {
setHasLoaded(true);
const storagedErrors = getMarathonErrorsStorage().get();
Expand All @@ -200,11 +262,6 @@ export default function MarathonForm({

useEffect(() => {
getMarathonErrorsStorage().set(errors);
if (Object.keys(errors).length) {
setHasErrors(true);
} else {
setHasErrors(false);
}
}, [errors]);

return (
Expand Down Expand Up @@ -245,7 +302,7 @@ export default function MarathonForm({
title="學習主題名稱"
value={newMarathon.title || ''}
onChange={(e) => {
handleOnChange('UPDATE_FIELD', 'title', e.target.value, 'title');
handleOnChange('title', e.target.value);
}}
sx={{
mb: '8px',
Expand Down Expand Up @@ -278,7 +335,7 @@ export default function MarathonForm({
<StyledTextareaAutosize
value={newMarathon.description || ''}
onChange={(e) => {
handleOnChange('UPDATE_FIELD', 'description', e.target.value, 'description');
handleOnChange('description', e.target.value);
}}
placeholder="範例:因為對剪影片和當 Youtuber 有興趣,我預計會研究搞笑型 Youtuber 的影片腳本與剪輯方式、拍攝我日常生活及練習剪輯,並建立 Youtube 頻道上傳影片。希望能藉此了解如何當一位 Youtuber。"
className={errors.description ? 'error' : ''}
Expand Down Expand Up @@ -323,15 +380,15 @@ export default function MarathonForm({
'生活發生變化',
'影響社會',
'受群體影響',
'其他:請在下方補上其他原因,並詳細說明動機'
'其他:請於下方撰寫'
]}
type="UPDATE_MOTIVATION_FIELD"
onChange={setNewMarathon}
selectedItems={newMarathon?.motivation?.tags || []}
/>
<StyledTextareaAutosize
onChange={(e) => {
handleOnChange('UPDATE_MOTIVATION_FIELD', 'description', e.target.value, 'motivationDescription');
handleOnChange('motivationDescription', e.target.value);
}}
className={errors.motivationDescription ? 'error' : ''}
value={newMarathon?.motivation?.description || ''}
Expand Down Expand Up @@ -360,7 +417,7 @@ export default function MarathonForm({
</Typography>
<StyledTextareaAutosize
onChange={(e) => {
handleOnChange('UPDATE_FIELD', 'goals', e.target.value, 'goals');
handleOnChange('goals', e.target.value);
}}
value={newMarathon.goals || ''}
placeholder="範例:
Expand Down Expand Up @@ -391,7 +448,7 @@ export default function MarathonForm({
</Typography>
<StyledTextareaAutosize
onChange={(e) => {
handleOnChange('UPDATE_FIELD', 'content', e.target.value, 'content');
handleOnChange('content', e.target.value);
}}
value={newMarathon.content || ''}
placeholder="範例:
Expand Down Expand Up @@ -442,15 +499,15 @@ export default function MarathonForm({
"田野調查",
"訪談",
"問卷調查",
"其他:請在下方補上其他原因,並詳細說明動機"
"其他:請於下方撰寫"
]}
type="UPDATE_STRATEGIES_FIELD"
onChange={setNewMarathon}
selectedItems={newMarathon?.strategies?.tags || []}
/>
<StyledTextareaAutosize
onChange={(e) => {
handleOnChange('UPDATE_STRATEGIES_FIELD', 'description', e.target.value, 'strategiesDescription');
handleOnChange('strategiesDescription', e.target.value);
}}
value={newMarathon?.strategies?.description || ''}
placeholder="範例:我預計會研究影片腳本、拍攝與剪輯方式,接著了解拍攝、剪輯與Youtube頻道經營,並同時練習拍攝與剪輯,開始經營頻道。我會用notion整理我收集到的資料以及筆記。"
Expand Down Expand Up @@ -483,7 +540,7 @@ export default function MarathonForm({
placeholder="範例:YouTube 創作者的實用資源"
value={newMarathon.resources || ''}
onChange={(e) => {
handleOnChange('UPDATE_FIELD', 'resources', e.target.value, 'resources');
handleOnChange('resources', e.target.value);
}}
className={errors.resources ? 'error' : 'warning'}
endAdornment={errors.resources ? <ClearIcon sx={{ color: '#EF5364' }} /> : null}
Expand Down Expand Up @@ -543,15 +600,15 @@ export default function MarathonForm({
"舉辦活動",
"開課",
"參與競賽",
"其他:請在下方補上其他原因,並詳細說明動機"
"其他:請於下方撰寫"
]}
type="UPDATE_OUTCOMES_FIELD"
onChange={setNewMarathon}
selectedItems={newMarathon?.outcomes?.tags || []}
/>
<StyledTextareaAutosize
onChange={(e) => {
handleOnChange('UPDATE_OUTCOMES_FIELD', 'description', e.target.value, 'outcomesDescription');
handleOnChange('outcomesDescription', e.target.value);
}}
value={newMarathon?.outcomes?.description || ''}
placeholder="範例:我預計會架設一個Youtube頻道,並上傳至少5支影片,並整理觀眾回饋與相關數據。"
Expand Down
6 changes: 3 additions & 3 deletions components/Marathon/SignUp/MilestoneGroup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function MilestoneGroup({
// if change frequency, clear all data
setFrequency(e.target.value);
const changedMilestones = calculateMilestones(startDate, e.target.value, []);
onChangeHandler('UPDATE_FIELD', 'milestones', changedMilestones, 'milestonesName');
onChangeHandler('milestonesName', changedMilestones);
};

const handleEndDate = (/** fakeDate */) => {
Expand All @@ -115,7 +115,7 @@ export default function MilestoneGroup({
const changedMilestones = milestones.map((item) => {
return (item._tempId === newMilestone._tempId ? newMilestone : item);
});
onChangeHandler('UPDATE_FIELD', 'milestones', changedMilestones, 'milestonesName');
onChangeHandler('milestonesName', changedMilestones);
};
useEffect(() => {
const weeklyMilestonesLength = 22;
Expand All @@ -132,7 +132,7 @@ export default function MilestoneGroup({
}

if (!isDisabled) {
onChangeHandler('UPDATE_FIELD', 'milestones', initMilestones, 'milestonesName');
onChangeHandler('milestonesName', initMilestones);
}
}, []);

Expand Down
Loading

0 comments on commit 90980b5

Please sign in to comment.