Stats.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import React, { Component, FC, useState, useEffect } from "react";
  2. import { bindActionCreators } from "redux";
  3. import { connect } from "react-redux";
  4. import Router from "next/router";
  5. import styled from "styled-components";
  6. import axios from "axios";
  7. import cookie from "js-cookie";
  8. import { Box, Flex } from "reflexbox/styled-components";
  9. import StatsError from "./StatsError";
  10. import StatsHead from "./StatsHead";
  11. import StatsCharts from "./StatsCharts";
  12. import PageLoading from "../PageLoading";
  13. import Button from "../Button";
  14. interface Props {
  15. isAuthenticated: boolean;
  16. domain: string;
  17. id: string;
  18. }
  19. const Title = styled.h2`
  20. font-size: 24px;
  21. font-weight: 300;
  22. a {
  23. color: #2196f3;
  24. text-decoration: none;
  25. border-bottom: 1px dotted transparent;
  26. :hover {
  27. border-bottom-color: #2196f3;
  28. }
  29. }
  30. @media only screen and (max-width: 768px) {
  31. font-size: 18px;
  32. }
  33. `;
  34. const TitleTarget = styled.p`
  35. font-size: 14px;
  36. text-align: right;
  37. color: #333;
  38. @media only screen and (max-width: 768px) {
  39. font-size: 11px;
  40. }
  41. `;
  42. const Content = styled(Flex).attrs({
  43. flex: "1 1 auto",
  44. flexDirection: "column"
  45. })`
  46. background-color: white;
  47. border-radius: 12px;
  48. box-shadow: 0 6px 30px rgba(50, 50, 50, 0.2);
  49. `;
  50. const Stats: FC<Props> = ({ domain, id, isAuthenticated }) => {
  51. const [loading, setLoading] = useState(true);
  52. const [error, setError] = useState(false);
  53. const [stats, setStats] = useState();
  54. const [period, setPeriod] = useState();
  55. useEffect(() => {
  56. if (id) return null;
  57. axios
  58. .get(`/api/url/stats?id=${id}&domain=${domain}`, {
  59. headers: { Authorization: cookie.get("token") }
  60. })
  61. .then(({ data }) => {
  62. setLoading(false);
  63. setError(!data);
  64. setStats(data);
  65. })
  66. .catch(() => {
  67. setLoading(false);
  68. setError(true);
  69. });
  70. }, []);
  71. const changePeriod = e => setPeriod(e.currentTarget.dataset.period);
  72. function goToHomepage(e) {
  73. e.preventDefault();
  74. Router.push("/");
  75. }
  76. if (!isAuthenticated)
  77. return <StatsError text="You need to login to view stats." />;
  78. if (!id || error) return <StatsError />;
  79. if (loading) return <PageLoading />;
  80. return (
  81. <Flex
  82. width={1200}
  83. maxWidth="95%"
  84. flexDirection="column"
  85. alignItems="stretch"
  86. m="40px 0"
  87. >
  88. <Flex justifyContent="space-between" alignItems="center">
  89. <Title>
  90. Stats for:{" "}
  91. <a href={stats.shortLink} title="Short link">
  92. {stats.shortLink.replace(/https?:\/\//, "")}
  93. </a>
  94. </Title>
  95. <TitleTarget>
  96. {stats.target.length > 80
  97. ? `${stats.target
  98. .split("")
  99. .slice(0, 80)
  100. .join("")}...`
  101. : stats.target}
  102. </TitleTarget>
  103. </Flex>
  104. <Content>
  105. <StatsHead
  106. total={stats.total}
  107. period={period}
  108. changePeriod={changePeriod}
  109. />
  110. <StatsCharts
  111. stats={stats[period]}
  112. updatedAt={stats.updatedAt}
  113. period={period}
  114. />
  115. </Content>
  116. <Box alignSelf="center" my={64}>
  117. <Button icon="arrow-left" onClick={goToHomepage}>
  118. Back to homepage
  119. </Button>
  120. </Box>
  121. </Flex>
  122. );
  123. };
  124. const mapStateToProps = ({ auth: { isAuthenticated } }) => ({
  125. isAuthenticated
  126. });
  127. export default connect(
  128. mapStateToProps,
  129. null
  130. )(Stats);