IssueTimeline.tsx 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import Issue from "../components/Issue"
  2. import Category from "../components/Category"
  3. import { useState } from "react"
  4. import { FormattedMessage, useIntl, defineMessages } from "react-intl"
  5. const messages = defineMessages({
  6. started: { id: "roadmap.state.started", defaultMessage: "In Progress" },
  7. unstarted: { id: "roadmap.state.unstarted", defaultMessage: "Planned" },
  8. backlog: { id: "roadmap.state.backlog", defaultMessage: "Exploring" },
  9. completed: {
  10. id: "roadmap.state.completed",
  11. defaultMessage: "Recently completed",
  12. },
  13. })
  14. export const IssueTimeline = ({ roadmap }) => {
  15. const intl = useIntl()
  16. const [activeCategory, setActiveCategory] = useState("all")
  17. const filteredRoadmap = roadmap
  18. .map((state) => {
  19. const filteredIssues = state.items.filter(
  20. ({ id }) => id.startsWith(activeCategory) || activeCategory === "all"
  21. )
  22. return {
  23. ...state,
  24. items: filteredIssues,
  25. }
  26. })
  27. .filter(({ items }) => items.length > 0)
  28. //prettier-ignore
  29. const categories = [
  30. { key: "all", label: intl.formatMessage({ id: "roadmap.all", defaultMessage: "All" }) },
  31. { key: "MAS", label: intl.formatMessage({ id: "roadmap.mastodon", defaultMessage: "Web / API" }) },
  32. { key: "IOS", label: intl.formatMessage({ id: "roadmap.ios", defaultMessage: "iOS" }) },
  33. { key: "AND", label: intl.formatMessage({ id: "roadmap.android", defaultMessage: "Android" }) },
  34. ]
  35. return (
  36. <div className="mt-56 pl-3 md:mt-0 md:rounded-md md:bg-white md:p-6">
  37. <div className="-mx-gutter ps-gutter mb-12 overflow-x-auto md:mb-6">
  38. <div className="flex flex-wrap gap-gutter md:flex-nowrap">
  39. {categories.map((category) => (
  40. <Category
  41. key={category.key}
  42. label={category.label}
  43. value={category.key}
  44. currentValue={activeCategory}
  45. onChange={(e) => setActiveCategory(e.target.value)}
  46. />
  47. ))}
  48. </div>
  49. </div>
  50. <div className="relative">
  51. <div className="absolute h-full w-0 border-l border-dashed border-gray-2" />
  52. {filteredRoadmap.map((state) => (
  53. <div key={state.type} className="mb-8 pl-4 md:pl-8">
  54. <h2 className="h6 mb-4 text-black">
  55. {intl.formatMessage(messages[state.type])}
  56. </h2>
  57. <div className="space-y-2">
  58. {state.items.map((issue) => (
  59. <Issue key={issue.id} state={state.type} {...issue} />
  60. ))}
  61. </div>
  62. </div>
  63. ))}
  64. </div>
  65. </div>
  66. )
  67. }
  68. export default IssueTimeline