We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
feedbackItemsStore.ts
import { create } from "zustand"; import { TFeedbackItem } from "../lib/types"; type Store = { feedbackItems: TFeedbackItem[]; isLoading: boolean; errorMessage: string; selectedCompany: string; actions: { getCompanyList: () => string[]; getFilteredFeedbackItems: () => TFeedbackItem[]; addItemToList: (text: string) => Promise<void>; selectCompany: (company: string) => void; fetchFeedbackItems: () => Promise<void>; }; }; export const useFeedbackItemsStore = create<Store>((set, get) => ({ feedbackItems: [], isLoading: false, errorMessage: "", selectedCompany: "", actions: { getCompanyList: () => { const state = get(); return state .feedbackItems.map((item) => item.company) .filter((company, index, array) => { return array.indexOf(company) === index; }); }, getFilteredFeedbackItems: () => { const state = get(); return state.selectedCompany ? state.feedbackItems.filter( (feedbackItem) => feedbackItem.company === state.selectedCompany ) : state.feedbackItems; }, addItemToList: async (text: string) => { const companyName = text .split(" ") .find((word) => word.includes("#"))! .substring(1); const newItem: TFeedbackItem = { id: new Date().getTime(), text: text, upvoteCount: 0, daysAgo: 0, company: companyName, badgeLetter: companyName.substring(0, 1).toUpperCase(), }; set((state) => ({ feedbackItems: [...state.feedbackItems, newItem], })); await fetch( "https://bytegrad.com/course-assets/projects/corpcomment/api/feedbacks", { method: "POST", body: JSON.stringify(newItem), headers: { Accept: "application/json", "Content-Type": "application/json", }, } ); }, selectCompany: (company: string) => { set(() => ({ selectedCompany: company, })); }, fetchFeedbackItems: async () => { set(() => ({ isLoading: true, })); try { const response = await fetch( "https://bytegrad.com/course-assets/projects/corpcomment/api/feedbacks" ); if (!response.ok) { throw new Error(); } const data = await response.json(); set(() => ({ feedbackItems: data.feedbacks, })); } catch (error) { set(() => ({ errorMessage: "Something went wrong. Please try again later.", })); } set(() => ({ isLoading: false, })); }, }, })); export const useFeedbackItems = () => useFeedbackItemsStore((state) => state.feedbackItems); export const useIsLoading = () => useFeedbackItemsStore((state) => state.isLoading); export const useErrorMessage = () => useFeedbackItemsStore((state) => state.errorMessage); export const useSelectedCompany = () => useFeedbackItemsStore((state) => state.selectedCompany); export const useFeedbackItemActions = () => useFeedbackItemsStore((state) => state.actions); export const useCompanyList = () => useFeedbackItemsStore((state) => state.actions.getCompanyList()); //Make sure it executes inside Zustand store. export const useFilteredFeedbackItems = () => useFeedbackItemsStore((state) => state.actions.getFilteredFeedbackItems()); //Make sure it executes inside Zustand store.
FeedbackForm.tsx
import { useState } from "react"; import { MAX_CHARACTERS } from "../../lib/constants"; import { useFeedbackItemActions } from "../../stores/feedbackItemsStore"; export default function FeedbackForm() { const {addItemToList} = useFeedbackItemActions(); const [text, setText] = useState(""); const [showValidIndicator, setShowValidIndicator] = useState(false); const [showInvalidIndicator, setShowInvalidIndicator] = useState(false); const charCount = MAX_CHARACTERS - text.length; const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { const newText = event.target.value; if (newText.length > MAX_CHARACTERS) { return; } setText(newText); }; const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); // basic validation if (text.includes("#") && text.length >= 5) { setShowValidIndicator(true); setTimeout(() => setShowValidIndicator(false), 2000); } else { setShowInvalidIndicator(true); setTimeout(() => setShowInvalidIndicator(false), 2000); return; } addItemToList(text); setText(""); }; return ( <form onSubmit={handleSubmit} className={`form ${showValidIndicator && "form--valid"} ${ showInvalidIndicator && "form--invalid" }`} > <textarea value={text} onChange={handleChange} id="feedback-textarea" placeholder="blabla" spellCheck={false} /> <label htmlFor="feedback-textarea"> Enter your feedback here, remember to #hashtag the company </label> <div> <p className="u-italic">{charCount}</p> <button> <span>Submit</span> </button> </div> </form> ); }
FeedbackList.tsx
import { useErrorMessage, useFilteredFeedbackItems, useIsLoading } from "../../stores/feedbackItemsStore"; import ErrorMessage from "../ErrorMessage"; import Spinner from "../Spinner"; import FeedbackItem from "./FeedbackItem"; export default function FeedbackList() { const isLoading = useIsLoading(); const errorMessage = useErrorMessage(); const filteredFeedbackItems = useFilteredFeedbackItems(); return ( <ol className="feedback-list"> {isLoading && <Spinner />} {errorMessage && <ErrorMessage message={errorMessage} />} {filteredFeedbackItems.map((feedbackItem) => ( <FeedbackItem key={feedbackItem.id} feedbackItem={feedbackItem} /> ))} </ol> ); }
HashtagItem.tsx
import { useFeedbackItemActions } from "../../stores/feedbackItemsStore"; type HashtagItemProps = { company: string; }; export default function HashtagItem({ company, }: HashtagItemProps) { const { selectCompany } = useFeedbackItemActions(); return ( <li key={company}> <button onClick={() => selectCompany(company)}>#{company}</button> </li> ); }
HashtagList.tsx
import { useCompanyList } from "../../stores/feedbackItemsStore"; import HashtagItem from "./HashtagItem"; export default function HashtagList() { const companyList = useCompanyList(); return ( <ul className="hashtags"> {companyList.map((company) => ( <HashtagItem key={company} company={company} /> ))} </ul> ); }
App.tsx
import { useEffect } from "react"; import { useFeedbackItemActions } from "../stores/feedbackItemsStore"; import HashtagList from "./hashtag/HashtagList"; import Container from "./layout/Container"; import Footer from "./layout/Footer"; function App() { const { fetchFeedbackItems } = useFeedbackItemActions(); useEffect(() => { fetchFeedbackItems(); }, [fetchFeedbackItems]); return ( <div className="app"> <Footer /> <Container /> <HashtagList /> </div> ); } export default App;
The text was updated successfully, but these errors were encountered:
No branches or pull requests
feedbackItemsStore.ts
FeedbackForm.tsx
FeedbackList.tsx
HashtagItem.tsx
HashtagList.tsx
App.tsx
The text was updated successfully, but these errors were encountered: