summaryrefslogtreecommitdiff
path: root/examples/snowpack/src/components/PluginSearchPage.jsx
blob: 51c7e6b0fa5492eeb2160dc9df0d5e4db5a37e20 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { h, Fragment } from 'preact';
import { useEffect, useState } from 'preact/hooks';
import Styles from './PluginSearchPage.module.css';

async function searchPlugins(val) {
  const params3 = new URLSearchParams([
    ['q', 'snowpack plugin ' + (val || '')],
    ['count', '100'],
  ]);
  const res = await fetch(
    `https://api.skypack.dev/v1/search?${params3.toString()}`,
  );
  const jsonres = await res.json();
  return jsonres.results;
}

function Card({ result }) {
  const updatedAtFormatted = Intl.DateTimeFormat('en', {
    month: 'long',
    day: 'numeric',
    year: 'numeric',
  }).format(Date.parse(result.updatedAt));
  return (
    <li class={Styles.Card}>
      <img class={Styles.Icon__Plugin} src="/img/plug-light.svg" />
      <header class={Styles.CardHeader}>
        <h3 class={Styles.CardName}>
          <a href="https://www.npmjs.com/package/{result.name}" target="_blank">
            <span itemprop="name">{result.name}</span>
          </a>
        </h3>
      </header>
      <p class={Styles.CardDesc} itemprop="description">
        {result.description.split('. ')[0]}
      </p>
      <p class={Styles.CardSubtitle}>
        Updated
        <time class="" datetime={result.updatedAt}>
          {updatedAtFormatted}
        </time>
      </p>
    </li>
  );
}

function PluginSearchPageLive() {
  const searchParams = new URLSearchParams(window.location.search);
  const [results, setResults] = useState(null);
  const [searchQuery, setSearchQuery] = useState(searchParams.get('q'));
  useEffect(() => {
    (async () => {
      setResults(await searchPlugins(searchParams.get('q')));
    })();
  }, []);

  async function onFormSubmit(e) {
    e.preventDefault();
    const form = new FormData(e.target);
    const formula = form.get('q');
    // document.getElementById('loading-message').style.display = 'block';
    const searchParams = new URLSearchParams(window.location.search);
    searchParams.set('q', formula);
    window.history.pushState(null, null, '?' + searchParams.toString());
    setSearchQuery(formula);
    setResults(await searchPlugins(formula));
    return false;
  }

  return (
    <>
      <form
        name="myform"
        id="myform"
        class={Styles.Form}
        action="https://www.npmjs.com/search"
        method="GET"
        onSubmit={onFormSubmit}
      >
        <input
          type="search"
          name="q"
          defaultValue={searchQuery}
          placeholder="search Sass, sitemaps, image optimization..."
          class={Styles.Input}
        />
        <button type="submit" class={Styles.Submit}>
          Search
        </button>
      </form>
      <div class={Styles.Count} id="total-result-count">
        {!searchQuery &&
          results &&
          results.length > 50 &&
          `${results.length}+ plugins available!`}
      </div>
      <section id="search-results" class={Styles.Results}>
        {!results && (
          <div id="loading-message" class={Styles.Loading}>
            Loading...
          </div>
        )}
        {results && results.length === 0 && (
          <ul class={Styles.CardList}>
            <li style="margin: 1rem; text-align: center;">No results found.</li>
          </ul>
        )}
        {results && results.length > 0 && (
          <ul class={Styles.CardList}>
            {results.map((r) => (
              <Card result={r} />
            ))}
          </ul>
        )}
      </section>
    </>
  );
}

export default function PluginSearchPage(props) {
  return import.meta.env.astro ? <div>Loading...</div> : <PluginSearchPageLive {...props} />
}